Path: blob/main/contrib/llvm-project/llvm/lib/IR/LLVMContextImpl.h
35233 views
//===- LLVMContextImpl.h - The LLVMContextImpl opaque class -----*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file declares LLVMContextImpl, the opaque implementation9// of LLVMContext.10//11//===----------------------------------------------------------------------===//1213#ifndef LLVM_LIB_IR_LLVMCONTEXTIMPL_H14#define LLVM_LIB_IR_LLVMCONTEXTIMPL_H1516#include "ConstantsContext.h"17#include "llvm/ADT/APFloat.h"18#include "llvm/ADT/APInt.h"19#include "llvm/ADT/ArrayRef.h"20#include "llvm/ADT/DenseMap.h"21#include "llvm/ADT/DenseMapInfo.h"22#include "llvm/ADT/DenseSet.h"23#include "llvm/ADT/FoldingSet.h"24#include "llvm/ADT/Hashing.h"25#include "llvm/ADT/STLExtras.h"26#include "llvm/ADT/SmallPtrSet.h"27#include "llvm/ADT/SmallVector.h"28#include "llvm/ADT/StringMap.h"29#include "llvm/BinaryFormat/Dwarf.h"30#include "llvm/IR/Constants.h"31#include "llvm/IR/DebugInfoMetadata.h"32#include "llvm/IR/DerivedTypes.h"33#include "llvm/IR/LLVMContext.h"34#include "llvm/IR/Metadata.h"35#include "llvm/IR/Module.h"36#include "llvm/IR/TrackingMDRef.h"37#include "llvm/IR/Type.h"38#include "llvm/IR/Value.h"39#include "llvm/Support/Allocator.h"40#include "llvm/Support/Casting.h"41#include "llvm/Support/StringSaver.h"42#include <algorithm>43#include <cassert>44#include <cstddef>45#include <cstdint>46#include <memory>47#include <optional>48#include <string>49#include <utility>50#include <vector>5152namespace llvm {5354class AttributeImpl;55class AttributeListImpl;56class AttributeSetNode;57class BasicBlock;58class ConstantRangeAttributeImpl;59class ConstantRangeListAttributeImpl;60struct DiagnosticHandler;61class DbgMarker;62class ElementCount;63class Function;64class GlobalObject;65class GlobalValue;66class InlineAsm;67class LLVMRemarkStreamer;68class OptPassGate;69namespace remarks {70class RemarkStreamer;71}72template <typename T> class StringMapEntry;73class StringRef;74class TypedPointerType;75class ValueHandleBase;7677template <> struct DenseMapInfo<APFloat> {78static inline APFloat getEmptyKey() { return APFloat(APFloat::Bogus(), 1); }79static inline APFloat getTombstoneKey() {80return APFloat(APFloat::Bogus(), 2);81}8283static unsigned getHashValue(const APFloat &Key) {84return static_cast<unsigned>(hash_value(Key));85}8687static bool isEqual(const APFloat &LHS, const APFloat &RHS) {88return LHS.bitwiseIsEqual(RHS);89}90};9192struct AnonStructTypeKeyInfo {93struct KeyTy {94ArrayRef<Type *> ETypes;95bool isPacked;9697KeyTy(const ArrayRef<Type *> &E, bool P) : ETypes(E), isPacked(P) {}9899KeyTy(const StructType *ST)100: ETypes(ST->elements()), isPacked(ST->isPacked()) {}101102bool operator==(const KeyTy &that) const {103if (isPacked != that.isPacked)104return false;105if (ETypes != that.ETypes)106return false;107return true;108}109bool operator!=(const KeyTy &that) const { return !this->operator==(that); }110};111112static inline StructType *getEmptyKey() {113return DenseMapInfo<StructType *>::getEmptyKey();114}115116static inline StructType *getTombstoneKey() {117return DenseMapInfo<StructType *>::getTombstoneKey();118}119120static unsigned getHashValue(const KeyTy &Key) {121return hash_combine(122hash_combine_range(Key.ETypes.begin(), Key.ETypes.end()), Key.isPacked);123}124125static unsigned getHashValue(const StructType *ST) {126return getHashValue(KeyTy(ST));127}128129static bool isEqual(const KeyTy &LHS, const StructType *RHS) {130if (RHS == getEmptyKey() || RHS == getTombstoneKey())131return false;132return LHS == KeyTy(RHS);133}134135static bool isEqual(const StructType *LHS, const StructType *RHS) {136return LHS == RHS;137}138};139140struct FunctionTypeKeyInfo {141struct KeyTy {142const Type *ReturnType;143ArrayRef<Type *> Params;144bool isVarArg;145146KeyTy(const Type *R, const ArrayRef<Type *> &P, bool V)147: ReturnType(R), Params(P), isVarArg(V) {}148KeyTy(const FunctionType *FT)149: ReturnType(FT->getReturnType()), Params(FT->params()),150isVarArg(FT->isVarArg()) {}151152bool operator==(const KeyTy &that) const {153if (ReturnType != that.ReturnType)154return false;155if (isVarArg != that.isVarArg)156return false;157if (Params != that.Params)158return false;159return true;160}161bool operator!=(const KeyTy &that) const { return !this->operator==(that); }162};163164static inline FunctionType *getEmptyKey() {165return DenseMapInfo<FunctionType *>::getEmptyKey();166}167168static inline FunctionType *getTombstoneKey() {169return DenseMapInfo<FunctionType *>::getTombstoneKey();170}171172static unsigned getHashValue(const KeyTy &Key) {173return hash_combine(174Key.ReturnType,175hash_combine_range(Key.Params.begin(), Key.Params.end()), Key.isVarArg);176}177178static unsigned getHashValue(const FunctionType *FT) {179return getHashValue(KeyTy(FT));180}181182static bool isEqual(const KeyTy &LHS, const FunctionType *RHS) {183if (RHS == getEmptyKey() || RHS == getTombstoneKey())184return false;185return LHS == KeyTy(RHS);186}187188static bool isEqual(const FunctionType *LHS, const FunctionType *RHS) {189return LHS == RHS;190}191};192193struct TargetExtTypeKeyInfo {194struct KeyTy {195StringRef Name;196ArrayRef<Type *> TypeParams;197ArrayRef<unsigned> IntParams;198199KeyTy(StringRef N, const ArrayRef<Type *> &TP, const ArrayRef<unsigned> &IP)200: Name(N), TypeParams(TP), IntParams(IP) {}201KeyTy(const TargetExtType *TT)202: Name(TT->getName()), TypeParams(TT->type_params()),203IntParams(TT->int_params()) {}204205bool operator==(const KeyTy &that) const {206return Name == that.Name && TypeParams == that.TypeParams &&207IntParams == that.IntParams;208}209bool operator!=(const KeyTy &that) const { return !this->operator==(that); }210};211212static inline TargetExtType *getEmptyKey() {213return DenseMapInfo<TargetExtType *>::getEmptyKey();214}215216static inline TargetExtType *getTombstoneKey() {217return DenseMapInfo<TargetExtType *>::getTombstoneKey();218}219220static unsigned getHashValue(const KeyTy &Key) {221return hash_combine(222Key.Name,223hash_combine_range(Key.TypeParams.begin(), Key.TypeParams.end()),224hash_combine_range(Key.IntParams.begin(), Key.IntParams.end()));225}226227static unsigned getHashValue(const TargetExtType *FT) {228return getHashValue(KeyTy(FT));229}230231static bool isEqual(const KeyTy &LHS, const TargetExtType *RHS) {232if (RHS == getEmptyKey() || RHS == getTombstoneKey())233return false;234return LHS == KeyTy(RHS);235}236237static bool isEqual(const TargetExtType *LHS, const TargetExtType *RHS) {238return LHS == RHS;239}240};241242/// Structure for hashing arbitrary MDNode operands.243class MDNodeOpsKey {244ArrayRef<Metadata *> RawOps;245ArrayRef<MDOperand> Ops;246unsigned Hash;247248protected:249MDNodeOpsKey(ArrayRef<Metadata *> Ops)250: RawOps(Ops), Hash(calculateHash(Ops)) {}251252template <class NodeTy>253MDNodeOpsKey(const NodeTy *N, unsigned Offset = 0)254: Ops(N->op_begin() + Offset, N->op_end()), Hash(N->getHash()) {}255256template <class NodeTy>257bool compareOps(const NodeTy *RHS, unsigned Offset = 0) const {258if (getHash() != RHS->getHash())259return false;260261assert((RawOps.empty() || Ops.empty()) && "Two sets of operands?");262return RawOps.empty() ? compareOps(Ops, RHS, Offset)263: compareOps(RawOps, RHS, Offset);264}265266static unsigned calculateHash(MDNode *N, unsigned Offset = 0);267268private:269template <class T>270static bool compareOps(ArrayRef<T> Ops, const MDNode *RHS, unsigned Offset) {271if (Ops.size() != RHS->getNumOperands() - Offset)272return false;273return std::equal(Ops.begin(), Ops.end(), RHS->op_begin() + Offset);274}275276static unsigned calculateHash(ArrayRef<Metadata *> Ops);277278public:279unsigned getHash() const { return Hash; }280};281282template <class NodeTy> struct MDNodeKeyImpl;283284/// Configuration point for MDNodeInfo::isEqual().285template <class NodeTy> struct MDNodeSubsetEqualImpl {286using KeyTy = MDNodeKeyImpl<NodeTy>;287288static bool isSubsetEqual(const KeyTy &LHS, const NodeTy *RHS) {289return false;290}291292static bool isSubsetEqual(const NodeTy *LHS, const NodeTy *RHS) {293return false;294}295};296297/// DenseMapInfo for MDTuple.298///299/// Note that we don't need the is-function-local bit, since that's implicit in300/// the operands.301template <> struct MDNodeKeyImpl<MDTuple> : MDNodeOpsKey {302MDNodeKeyImpl(ArrayRef<Metadata *> Ops) : MDNodeOpsKey(Ops) {}303MDNodeKeyImpl(const MDTuple *N) : MDNodeOpsKey(N) {}304305bool isKeyOf(const MDTuple *RHS) const { return compareOps(RHS); }306307unsigned getHashValue() const { return getHash(); }308309static unsigned calculateHash(MDTuple *N) {310return MDNodeOpsKey::calculateHash(N);311}312};313314/// DenseMapInfo for DILocation.315template <> struct MDNodeKeyImpl<DILocation> {316unsigned Line;317unsigned Column;318Metadata *Scope;319Metadata *InlinedAt;320bool ImplicitCode;321322MDNodeKeyImpl(unsigned Line, unsigned Column, Metadata *Scope,323Metadata *InlinedAt, bool ImplicitCode)324: Line(Line), Column(Column), Scope(Scope), InlinedAt(InlinedAt),325ImplicitCode(ImplicitCode) {}326MDNodeKeyImpl(const DILocation *L)327: Line(L->getLine()), Column(L->getColumn()), Scope(L->getRawScope()),328InlinedAt(L->getRawInlinedAt()), ImplicitCode(L->isImplicitCode()) {}329330bool isKeyOf(const DILocation *RHS) const {331return Line == RHS->getLine() && Column == RHS->getColumn() &&332Scope == RHS->getRawScope() && InlinedAt == RHS->getRawInlinedAt() &&333ImplicitCode == RHS->isImplicitCode();334}335336unsigned getHashValue() const {337return hash_combine(Line, Column, Scope, InlinedAt, ImplicitCode);338}339};340341/// DenseMapInfo for GenericDINode.342template <> struct MDNodeKeyImpl<GenericDINode> : MDNodeOpsKey {343unsigned Tag;344MDString *Header;345346MDNodeKeyImpl(unsigned Tag, MDString *Header, ArrayRef<Metadata *> DwarfOps)347: MDNodeOpsKey(DwarfOps), Tag(Tag), Header(Header) {}348MDNodeKeyImpl(const GenericDINode *N)349: MDNodeOpsKey(N, 1), Tag(N->getTag()), Header(N->getRawHeader()) {}350351bool isKeyOf(const GenericDINode *RHS) const {352return Tag == RHS->getTag() && Header == RHS->getRawHeader() &&353compareOps(RHS, 1);354}355356unsigned getHashValue() const { return hash_combine(getHash(), Tag, Header); }357358static unsigned calculateHash(GenericDINode *N) {359return MDNodeOpsKey::calculateHash(N, 1);360}361};362363template <> struct MDNodeKeyImpl<DISubrange> {364Metadata *CountNode;365Metadata *LowerBound;366Metadata *UpperBound;367Metadata *Stride;368369MDNodeKeyImpl(Metadata *CountNode, Metadata *LowerBound, Metadata *UpperBound,370Metadata *Stride)371: CountNode(CountNode), LowerBound(LowerBound), UpperBound(UpperBound),372Stride(Stride) {}373MDNodeKeyImpl(const DISubrange *N)374: CountNode(N->getRawCountNode()), LowerBound(N->getRawLowerBound()),375UpperBound(N->getRawUpperBound()), Stride(N->getRawStride()) {}376377bool isKeyOf(const DISubrange *RHS) const {378auto BoundsEqual = [=](Metadata *Node1, Metadata *Node2) -> bool {379if (Node1 == Node2)380return true;381382ConstantAsMetadata *MD1 = dyn_cast_or_null<ConstantAsMetadata>(Node1);383ConstantAsMetadata *MD2 = dyn_cast_or_null<ConstantAsMetadata>(Node2);384if (MD1 && MD2) {385ConstantInt *CV1 = cast<ConstantInt>(MD1->getValue());386ConstantInt *CV2 = cast<ConstantInt>(MD2->getValue());387if (CV1->getSExtValue() == CV2->getSExtValue())388return true;389}390return false;391};392393return BoundsEqual(CountNode, RHS->getRawCountNode()) &&394BoundsEqual(LowerBound, RHS->getRawLowerBound()) &&395BoundsEqual(UpperBound, RHS->getRawUpperBound()) &&396BoundsEqual(Stride, RHS->getRawStride());397}398399unsigned getHashValue() const {400if (CountNode)401if (auto *MD = dyn_cast<ConstantAsMetadata>(CountNode))402return hash_combine(cast<ConstantInt>(MD->getValue())->getSExtValue(),403LowerBound, UpperBound, Stride);404return hash_combine(CountNode, LowerBound, UpperBound, Stride);405}406};407408template <> struct MDNodeKeyImpl<DIGenericSubrange> {409Metadata *CountNode;410Metadata *LowerBound;411Metadata *UpperBound;412Metadata *Stride;413414MDNodeKeyImpl(Metadata *CountNode, Metadata *LowerBound, Metadata *UpperBound,415Metadata *Stride)416: CountNode(CountNode), LowerBound(LowerBound), UpperBound(UpperBound),417Stride(Stride) {}418MDNodeKeyImpl(const DIGenericSubrange *N)419: CountNode(N->getRawCountNode()), LowerBound(N->getRawLowerBound()),420UpperBound(N->getRawUpperBound()), Stride(N->getRawStride()) {}421422bool isKeyOf(const DIGenericSubrange *RHS) const {423return (CountNode == RHS->getRawCountNode()) &&424(LowerBound == RHS->getRawLowerBound()) &&425(UpperBound == RHS->getRawUpperBound()) &&426(Stride == RHS->getRawStride());427}428429unsigned getHashValue() const {430auto *MD = dyn_cast_or_null<ConstantAsMetadata>(CountNode);431if (CountNode && MD)432return hash_combine(cast<ConstantInt>(MD->getValue())->getSExtValue(),433LowerBound, UpperBound, Stride);434return hash_combine(CountNode, LowerBound, UpperBound, Stride);435}436};437438template <> struct MDNodeKeyImpl<DIEnumerator> {439APInt Value;440MDString *Name;441bool IsUnsigned;442443MDNodeKeyImpl(APInt Value, bool IsUnsigned, MDString *Name)444: Value(std::move(Value)), Name(Name), IsUnsigned(IsUnsigned) {}445MDNodeKeyImpl(int64_t Value, bool IsUnsigned, MDString *Name)446: Value(APInt(64, Value, !IsUnsigned)), Name(Name),447IsUnsigned(IsUnsigned) {}448MDNodeKeyImpl(const DIEnumerator *N)449: Value(N->getValue()), Name(N->getRawName()),450IsUnsigned(N->isUnsigned()) {}451452bool isKeyOf(const DIEnumerator *RHS) const {453return Value.getBitWidth() == RHS->getValue().getBitWidth() &&454Value == RHS->getValue() && IsUnsigned == RHS->isUnsigned() &&455Name == RHS->getRawName();456}457458unsigned getHashValue() const { return hash_combine(Value, Name); }459};460461template <> struct MDNodeKeyImpl<DIBasicType> {462unsigned Tag;463MDString *Name;464uint64_t SizeInBits;465uint32_t AlignInBits;466unsigned Encoding;467unsigned Flags;468469MDNodeKeyImpl(unsigned Tag, MDString *Name, uint64_t SizeInBits,470uint32_t AlignInBits, unsigned Encoding, unsigned Flags)471: Tag(Tag), Name(Name), SizeInBits(SizeInBits), AlignInBits(AlignInBits),472Encoding(Encoding), Flags(Flags) {}473MDNodeKeyImpl(const DIBasicType *N)474: Tag(N->getTag()), Name(N->getRawName()), SizeInBits(N->getSizeInBits()),475AlignInBits(N->getAlignInBits()), Encoding(N->getEncoding()),476Flags(N->getFlags()) {}477478bool isKeyOf(const DIBasicType *RHS) const {479return Tag == RHS->getTag() && Name == RHS->getRawName() &&480SizeInBits == RHS->getSizeInBits() &&481AlignInBits == RHS->getAlignInBits() &&482Encoding == RHS->getEncoding() && Flags == RHS->getFlags();483}484485unsigned getHashValue() const {486return hash_combine(Tag, Name, SizeInBits, AlignInBits, Encoding);487}488};489490template <> struct MDNodeKeyImpl<DIStringType> {491unsigned Tag;492MDString *Name;493Metadata *StringLength;494Metadata *StringLengthExp;495Metadata *StringLocationExp;496uint64_t SizeInBits;497uint32_t AlignInBits;498unsigned Encoding;499500MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *StringLength,501Metadata *StringLengthExp, Metadata *StringLocationExp,502uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding)503: Tag(Tag), Name(Name), StringLength(StringLength),504StringLengthExp(StringLengthExp), StringLocationExp(StringLocationExp),505SizeInBits(SizeInBits), AlignInBits(AlignInBits), Encoding(Encoding) {}506MDNodeKeyImpl(const DIStringType *N)507: Tag(N->getTag()), Name(N->getRawName()),508StringLength(N->getRawStringLength()),509StringLengthExp(N->getRawStringLengthExp()),510StringLocationExp(N->getRawStringLocationExp()),511SizeInBits(N->getSizeInBits()), AlignInBits(N->getAlignInBits()),512Encoding(N->getEncoding()) {}513514bool isKeyOf(const DIStringType *RHS) const {515return Tag == RHS->getTag() && Name == RHS->getRawName() &&516StringLength == RHS->getRawStringLength() &&517StringLengthExp == RHS->getRawStringLengthExp() &&518StringLocationExp == RHS->getRawStringLocationExp() &&519SizeInBits == RHS->getSizeInBits() &&520AlignInBits == RHS->getAlignInBits() &&521Encoding == RHS->getEncoding();522}523unsigned getHashValue() const {524// Intentionally computes the hash on a subset of the operands for525// performance reason. The subset has to be significant enough to avoid526// collision "most of the time". There is no correctness issue in case of527// collision because of the full check above.528return hash_combine(Tag, Name, StringLength, Encoding);529}530};531532template <> struct MDNodeKeyImpl<DIDerivedType> {533unsigned Tag;534MDString *Name;535Metadata *File;536unsigned Line;537Metadata *Scope;538Metadata *BaseType;539uint64_t SizeInBits;540uint64_t OffsetInBits;541uint32_t AlignInBits;542std::optional<unsigned> DWARFAddressSpace;543std::optional<DIDerivedType::PtrAuthData> PtrAuthData;544unsigned Flags;545Metadata *ExtraData;546Metadata *Annotations;547548MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,549Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,550uint32_t AlignInBits, uint64_t OffsetInBits,551std::optional<unsigned> DWARFAddressSpace,552std::optional<DIDerivedType::PtrAuthData> PtrAuthData,553unsigned Flags, Metadata *ExtraData, Metadata *Annotations)554: Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),555BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits),556AlignInBits(AlignInBits), DWARFAddressSpace(DWARFAddressSpace),557PtrAuthData(PtrAuthData), Flags(Flags), ExtraData(ExtraData),558Annotations(Annotations) {}559MDNodeKeyImpl(const DIDerivedType *N)560: Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),561Line(N->getLine()), Scope(N->getRawScope()),562BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()),563OffsetInBits(N->getOffsetInBits()), AlignInBits(N->getAlignInBits()),564DWARFAddressSpace(N->getDWARFAddressSpace()),565PtrAuthData(N->getPtrAuthData()), Flags(N->getFlags()),566ExtraData(N->getRawExtraData()), Annotations(N->getRawAnnotations()) {}567568bool isKeyOf(const DIDerivedType *RHS) const {569return Tag == RHS->getTag() && Name == RHS->getRawName() &&570File == RHS->getRawFile() && Line == RHS->getLine() &&571Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() &&572SizeInBits == RHS->getSizeInBits() &&573AlignInBits == RHS->getAlignInBits() &&574OffsetInBits == RHS->getOffsetInBits() &&575DWARFAddressSpace == RHS->getDWARFAddressSpace() &&576PtrAuthData == RHS->getPtrAuthData() && Flags == RHS->getFlags() &&577ExtraData == RHS->getRawExtraData() &&578Annotations == RHS->getRawAnnotations();579}580581unsigned getHashValue() const {582// If this is a member inside an ODR type, only hash the type and the name.583// Otherwise the hash will be stronger than584// MDNodeSubsetEqualImpl::isODRMember().585if (Tag == dwarf::DW_TAG_member && Name)586if (auto *CT = dyn_cast_or_null<DICompositeType>(Scope))587if (CT->getRawIdentifier())588return hash_combine(Name, Scope);589590// Intentionally computes the hash on a subset of the operands for591// performance reason. The subset has to be significant enough to avoid592// collision "most of the time". There is no correctness issue in case of593// collision because of the full check above.594return hash_combine(Tag, Name, File, Line, Scope, BaseType, Flags);595}596};597598template <> struct MDNodeSubsetEqualImpl<DIDerivedType> {599using KeyTy = MDNodeKeyImpl<DIDerivedType>;600601static bool isSubsetEqual(const KeyTy &LHS, const DIDerivedType *RHS) {602return isODRMember(LHS.Tag, LHS.Scope, LHS.Name, RHS);603}604605static bool isSubsetEqual(const DIDerivedType *LHS,606const DIDerivedType *RHS) {607return isODRMember(LHS->getTag(), LHS->getRawScope(), LHS->getRawName(),608RHS);609}610611/// Subprograms compare equal if they declare the same function in an ODR612/// type.613static bool isODRMember(unsigned Tag, const Metadata *Scope,614const MDString *Name, const DIDerivedType *RHS) {615// Check whether the LHS is eligible.616if (Tag != dwarf::DW_TAG_member || !Name)617return false;618619auto *CT = dyn_cast_or_null<DICompositeType>(Scope);620if (!CT || !CT->getRawIdentifier())621return false;622623// Compare to the RHS.624return Tag == RHS->getTag() && Name == RHS->getRawName() &&625Scope == RHS->getRawScope();626}627};628629template <> struct MDNodeKeyImpl<DICompositeType> {630unsigned Tag;631MDString *Name;632Metadata *File;633unsigned Line;634Metadata *Scope;635Metadata *BaseType;636uint64_t SizeInBits;637uint64_t OffsetInBits;638uint32_t AlignInBits;639unsigned Flags;640Metadata *Elements;641unsigned RuntimeLang;642Metadata *VTableHolder;643Metadata *TemplateParams;644MDString *Identifier;645Metadata *Discriminator;646Metadata *DataLocation;647Metadata *Associated;648Metadata *Allocated;649Metadata *Rank;650Metadata *Annotations;651652MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *File, unsigned Line,653Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,654uint32_t AlignInBits, uint64_t OffsetInBits, unsigned Flags,655Metadata *Elements, unsigned RuntimeLang,656Metadata *VTableHolder, Metadata *TemplateParams,657MDString *Identifier, Metadata *Discriminator,658Metadata *DataLocation, Metadata *Associated,659Metadata *Allocated, Metadata *Rank, Metadata *Annotations)660: Tag(Tag), Name(Name), File(File), Line(Line), Scope(Scope),661BaseType(BaseType), SizeInBits(SizeInBits), OffsetInBits(OffsetInBits),662AlignInBits(AlignInBits), Flags(Flags), Elements(Elements),663RuntimeLang(RuntimeLang), VTableHolder(VTableHolder),664TemplateParams(TemplateParams), Identifier(Identifier),665Discriminator(Discriminator), DataLocation(DataLocation),666Associated(Associated), Allocated(Allocated), Rank(Rank),667Annotations(Annotations) {}668MDNodeKeyImpl(const DICompositeType *N)669: Tag(N->getTag()), Name(N->getRawName()), File(N->getRawFile()),670Line(N->getLine()), Scope(N->getRawScope()),671BaseType(N->getRawBaseType()), SizeInBits(N->getSizeInBits()),672OffsetInBits(N->getOffsetInBits()), AlignInBits(N->getAlignInBits()),673Flags(N->getFlags()), Elements(N->getRawElements()),674RuntimeLang(N->getRuntimeLang()), VTableHolder(N->getRawVTableHolder()),675TemplateParams(N->getRawTemplateParams()),676Identifier(N->getRawIdentifier()),677Discriminator(N->getRawDiscriminator()),678DataLocation(N->getRawDataLocation()),679Associated(N->getRawAssociated()), Allocated(N->getRawAllocated()),680Rank(N->getRawRank()), Annotations(N->getRawAnnotations()) {}681682bool isKeyOf(const DICompositeType *RHS) const {683return Tag == RHS->getTag() && Name == RHS->getRawName() &&684File == RHS->getRawFile() && Line == RHS->getLine() &&685Scope == RHS->getRawScope() && BaseType == RHS->getRawBaseType() &&686SizeInBits == RHS->getSizeInBits() &&687AlignInBits == RHS->getAlignInBits() &&688OffsetInBits == RHS->getOffsetInBits() && Flags == RHS->getFlags() &&689Elements == RHS->getRawElements() &&690RuntimeLang == RHS->getRuntimeLang() &&691VTableHolder == RHS->getRawVTableHolder() &&692TemplateParams == RHS->getRawTemplateParams() &&693Identifier == RHS->getRawIdentifier() &&694Discriminator == RHS->getRawDiscriminator() &&695DataLocation == RHS->getRawDataLocation() &&696Associated == RHS->getRawAssociated() &&697Allocated == RHS->getRawAllocated() && Rank == RHS->getRawRank() &&698Annotations == RHS->getRawAnnotations();699}700701unsigned getHashValue() const {702// Intentionally computes the hash on a subset of the operands for703// performance reason. The subset has to be significant enough to avoid704// collision "most of the time". There is no correctness issue in case of705// collision because of the full check above.706return hash_combine(Name, File, Line, BaseType, Scope, Elements,707TemplateParams, Annotations);708}709};710711template <> struct MDNodeKeyImpl<DISubroutineType> {712unsigned Flags;713uint8_t CC;714Metadata *TypeArray;715716MDNodeKeyImpl(unsigned Flags, uint8_t CC, Metadata *TypeArray)717: Flags(Flags), CC(CC), TypeArray(TypeArray) {}718MDNodeKeyImpl(const DISubroutineType *N)719: Flags(N->getFlags()), CC(N->getCC()), TypeArray(N->getRawTypeArray()) {}720721bool isKeyOf(const DISubroutineType *RHS) const {722return Flags == RHS->getFlags() && CC == RHS->getCC() &&723TypeArray == RHS->getRawTypeArray();724}725726unsigned getHashValue() const { return hash_combine(Flags, CC, TypeArray); }727};728729template <> struct MDNodeKeyImpl<DIFile> {730MDString *Filename;731MDString *Directory;732std::optional<DIFile::ChecksumInfo<MDString *>> Checksum;733MDString *Source;734735MDNodeKeyImpl(MDString *Filename, MDString *Directory,736std::optional<DIFile::ChecksumInfo<MDString *>> Checksum,737MDString *Source)738: Filename(Filename), Directory(Directory), Checksum(Checksum),739Source(Source) {}740MDNodeKeyImpl(const DIFile *N)741: Filename(N->getRawFilename()), Directory(N->getRawDirectory()),742Checksum(N->getRawChecksum()), Source(N->getRawSource()) {}743744bool isKeyOf(const DIFile *RHS) const {745return Filename == RHS->getRawFilename() &&746Directory == RHS->getRawDirectory() &&747Checksum == RHS->getRawChecksum() && Source == RHS->getRawSource();748}749750unsigned getHashValue() const {751return hash_combine(Filename, Directory, Checksum ? Checksum->Kind : 0,752Checksum ? Checksum->Value : nullptr, Source);753}754};755756template <> struct MDNodeKeyImpl<DISubprogram> {757Metadata *Scope;758MDString *Name;759MDString *LinkageName;760Metadata *File;761unsigned Line;762Metadata *Type;763unsigned ScopeLine;764Metadata *ContainingType;765unsigned VirtualIndex;766int ThisAdjustment;767unsigned Flags;768unsigned SPFlags;769Metadata *Unit;770Metadata *TemplateParams;771Metadata *Declaration;772Metadata *RetainedNodes;773Metadata *ThrownTypes;774Metadata *Annotations;775MDString *TargetFuncName;776777MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName,778Metadata *File, unsigned Line, Metadata *Type,779unsigned ScopeLine, Metadata *ContainingType,780unsigned VirtualIndex, int ThisAdjustment, unsigned Flags,781unsigned SPFlags, Metadata *Unit, Metadata *TemplateParams,782Metadata *Declaration, Metadata *RetainedNodes,783Metadata *ThrownTypes, Metadata *Annotations,784MDString *TargetFuncName)785: Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),786Line(Line), Type(Type), ScopeLine(ScopeLine),787ContainingType(ContainingType), VirtualIndex(VirtualIndex),788ThisAdjustment(ThisAdjustment), Flags(Flags), SPFlags(SPFlags),789Unit(Unit), TemplateParams(TemplateParams), Declaration(Declaration),790RetainedNodes(RetainedNodes), ThrownTypes(ThrownTypes),791Annotations(Annotations), TargetFuncName(TargetFuncName) {}792MDNodeKeyImpl(const DISubprogram *N)793: Scope(N->getRawScope()), Name(N->getRawName()),794LinkageName(N->getRawLinkageName()), File(N->getRawFile()),795Line(N->getLine()), Type(N->getRawType()), ScopeLine(N->getScopeLine()),796ContainingType(N->getRawContainingType()),797VirtualIndex(N->getVirtualIndex()),798ThisAdjustment(N->getThisAdjustment()), Flags(N->getFlags()),799SPFlags(N->getSPFlags()), Unit(N->getRawUnit()),800TemplateParams(N->getRawTemplateParams()),801Declaration(N->getRawDeclaration()),802RetainedNodes(N->getRawRetainedNodes()),803ThrownTypes(N->getRawThrownTypes()),804Annotations(N->getRawAnnotations()),805TargetFuncName(N->getRawTargetFuncName()) {}806807bool isKeyOf(const DISubprogram *RHS) const {808return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&809LinkageName == RHS->getRawLinkageName() &&810File == RHS->getRawFile() && Line == RHS->getLine() &&811Type == RHS->getRawType() && ScopeLine == RHS->getScopeLine() &&812ContainingType == RHS->getRawContainingType() &&813VirtualIndex == RHS->getVirtualIndex() &&814ThisAdjustment == RHS->getThisAdjustment() &&815Flags == RHS->getFlags() && SPFlags == RHS->getSPFlags() &&816Unit == RHS->getUnit() &&817TemplateParams == RHS->getRawTemplateParams() &&818Declaration == RHS->getRawDeclaration() &&819RetainedNodes == RHS->getRawRetainedNodes() &&820ThrownTypes == RHS->getRawThrownTypes() &&821Annotations == RHS->getRawAnnotations() &&822TargetFuncName == RHS->getRawTargetFuncName();823}824825bool isDefinition() const { return SPFlags & DISubprogram::SPFlagDefinition; }826827unsigned getHashValue() const {828// Use the Scope's linkage name instead of using the scope directly, as the829// scope may be a temporary one which can replaced, which would produce a830// different hash for the same DISubprogram.831llvm::StringRef ScopeLinkageName;832if (auto *CT = dyn_cast_or_null<DICompositeType>(Scope))833if (auto *ID = CT->getRawIdentifier())834ScopeLinkageName = ID->getString();835836// If this is a declaration inside an ODR type, only hash the type and the837// name. Otherwise the hash will be stronger than838// MDNodeSubsetEqualImpl::isDeclarationOfODRMember().839if (!isDefinition() && LinkageName &&840isa_and_nonnull<DICompositeType>(Scope))841return hash_combine(LinkageName, ScopeLinkageName);842843// Intentionally computes the hash on a subset of the operands for844// performance reason. The subset has to be significant enough to avoid845// collision "most of the time". There is no correctness issue in case of846// collision because of the full check above.847return hash_combine(Name, ScopeLinkageName, File, Type, Line);848}849};850851template <> struct MDNodeSubsetEqualImpl<DISubprogram> {852using KeyTy = MDNodeKeyImpl<DISubprogram>;853854static bool isSubsetEqual(const KeyTy &LHS, const DISubprogram *RHS) {855return isDeclarationOfODRMember(LHS.isDefinition(), LHS.Scope,856LHS.LinkageName, LHS.TemplateParams, RHS);857}858859static bool isSubsetEqual(const DISubprogram *LHS, const DISubprogram *RHS) {860return isDeclarationOfODRMember(LHS->isDefinition(), LHS->getRawScope(),861LHS->getRawLinkageName(),862LHS->getRawTemplateParams(), RHS);863}864865/// Subprograms compare equal if they declare the same function in an ODR866/// type.867static bool isDeclarationOfODRMember(bool IsDefinition, const Metadata *Scope,868const MDString *LinkageName,869const Metadata *TemplateParams,870const DISubprogram *RHS) {871// Check whether the LHS is eligible.872if (IsDefinition || !Scope || !LinkageName)873return false;874875auto *CT = dyn_cast_or_null<DICompositeType>(Scope);876if (!CT || !CT->getRawIdentifier())877return false;878879// Compare to the RHS.880// FIXME: We need to compare template parameters here to avoid incorrect881// collisions in mapMetadata when RF_ReuseAndMutateDistinctMDs and a882// ODR-DISubprogram has a non-ODR template parameter (i.e., a883// DICompositeType that does not have an identifier). Eventually we should884// decouple ODR logic from uniquing logic.885return IsDefinition == RHS->isDefinition() && Scope == RHS->getRawScope() &&886LinkageName == RHS->getRawLinkageName() &&887TemplateParams == RHS->getRawTemplateParams();888}889};890891template <> struct MDNodeKeyImpl<DILexicalBlock> {892Metadata *Scope;893Metadata *File;894unsigned Line;895unsigned Column;896897MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Line, unsigned Column)898: Scope(Scope), File(File), Line(Line), Column(Column) {}899MDNodeKeyImpl(const DILexicalBlock *N)900: Scope(N->getRawScope()), File(N->getRawFile()), Line(N->getLine()),901Column(N->getColumn()) {}902903bool isKeyOf(const DILexicalBlock *RHS) const {904return Scope == RHS->getRawScope() && File == RHS->getRawFile() &&905Line == RHS->getLine() && Column == RHS->getColumn();906}907908unsigned getHashValue() const {909return hash_combine(Scope, File, Line, Column);910}911};912913template <> struct MDNodeKeyImpl<DILexicalBlockFile> {914Metadata *Scope;915Metadata *File;916unsigned Discriminator;917918MDNodeKeyImpl(Metadata *Scope, Metadata *File, unsigned Discriminator)919: Scope(Scope), File(File), Discriminator(Discriminator) {}920MDNodeKeyImpl(const DILexicalBlockFile *N)921: Scope(N->getRawScope()), File(N->getRawFile()),922Discriminator(N->getDiscriminator()) {}923924bool isKeyOf(const DILexicalBlockFile *RHS) const {925return Scope == RHS->getRawScope() && File == RHS->getRawFile() &&926Discriminator == RHS->getDiscriminator();927}928929unsigned getHashValue() const {930return hash_combine(Scope, File, Discriminator);931}932};933934template <> struct MDNodeKeyImpl<DINamespace> {935Metadata *Scope;936MDString *Name;937bool ExportSymbols;938939MDNodeKeyImpl(Metadata *Scope, MDString *Name, bool ExportSymbols)940: Scope(Scope), Name(Name), ExportSymbols(ExportSymbols) {}941MDNodeKeyImpl(const DINamespace *N)942: Scope(N->getRawScope()), Name(N->getRawName()),943ExportSymbols(N->getExportSymbols()) {}944945bool isKeyOf(const DINamespace *RHS) const {946return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&947ExportSymbols == RHS->getExportSymbols();948}949950unsigned getHashValue() const { return hash_combine(Scope, Name); }951};952953template <> struct MDNodeKeyImpl<DICommonBlock> {954Metadata *Scope;955Metadata *Decl;956MDString *Name;957Metadata *File;958unsigned LineNo;959960MDNodeKeyImpl(Metadata *Scope, Metadata *Decl, MDString *Name, Metadata *File,961unsigned LineNo)962: Scope(Scope), Decl(Decl), Name(Name), File(File), LineNo(LineNo) {}963MDNodeKeyImpl(const DICommonBlock *N)964: Scope(N->getRawScope()), Decl(N->getRawDecl()), Name(N->getRawName()),965File(N->getRawFile()), LineNo(N->getLineNo()) {}966967bool isKeyOf(const DICommonBlock *RHS) const {968return Scope == RHS->getRawScope() && Decl == RHS->getRawDecl() &&969Name == RHS->getRawName() && File == RHS->getRawFile() &&970LineNo == RHS->getLineNo();971}972973unsigned getHashValue() const {974return hash_combine(Scope, Decl, Name, File, LineNo);975}976};977978template <> struct MDNodeKeyImpl<DIModule> {979Metadata *File;980Metadata *Scope;981MDString *Name;982MDString *ConfigurationMacros;983MDString *IncludePath;984MDString *APINotesFile;985unsigned LineNo;986bool IsDecl;987988MDNodeKeyImpl(Metadata *File, Metadata *Scope, MDString *Name,989MDString *ConfigurationMacros, MDString *IncludePath,990MDString *APINotesFile, unsigned LineNo, bool IsDecl)991: File(File), Scope(Scope), Name(Name),992ConfigurationMacros(ConfigurationMacros), IncludePath(IncludePath),993APINotesFile(APINotesFile), LineNo(LineNo), IsDecl(IsDecl) {}994MDNodeKeyImpl(const DIModule *N)995: File(N->getRawFile()), Scope(N->getRawScope()), Name(N->getRawName()),996ConfigurationMacros(N->getRawConfigurationMacros()),997IncludePath(N->getRawIncludePath()),998APINotesFile(N->getRawAPINotesFile()), LineNo(N->getLineNo()),999IsDecl(N->getIsDecl()) {}10001001bool isKeyOf(const DIModule *RHS) const {1002return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&1003ConfigurationMacros == RHS->getRawConfigurationMacros() &&1004IncludePath == RHS->getRawIncludePath() &&1005APINotesFile == RHS->getRawAPINotesFile() &&1006File == RHS->getRawFile() && LineNo == RHS->getLineNo() &&1007IsDecl == RHS->getIsDecl();1008}10091010unsigned getHashValue() const {1011return hash_combine(Scope, Name, ConfigurationMacros, IncludePath);1012}1013};10141015template <> struct MDNodeKeyImpl<DITemplateTypeParameter> {1016MDString *Name;1017Metadata *Type;1018bool IsDefault;10191020MDNodeKeyImpl(MDString *Name, Metadata *Type, bool IsDefault)1021: Name(Name), Type(Type), IsDefault(IsDefault) {}1022MDNodeKeyImpl(const DITemplateTypeParameter *N)1023: Name(N->getRawName()), Type(N->getRawType()),1024IsDefault(N->isDefault()) {}10251026bool isKeyOf(const DITemplateTypeParameter *RHS) const {1027return Name == RHS->getRawName() && Type == RHS->getRawType() &&1028IsDefault == RHS->isDefault();1029}10301031unsigned getHashValue() const { return hash_combine(Name, Type, IsDefault); }1032};10331034template <> struct MDNodeKeyImpl<DITemplateValueParameter> {1035unsigned Tag;1036MDString *Name;1037Metadata *Type;1038bool IsDefault;1039Metadata *Value;10401041MDNodeKeyImpl(unsigned Tag, MDString *Name, Metadata *Type, bool IsDefault,1042Metadata *Value)1043: Tag(Tag), Name(Name), Type(Type), IsDefault(IsDefault), Value(Value) {}1044MDNodeKeyImpl(const DITemplateValueParameter *N)1045: Tag(N->getTag()), Name(N->getRawName()), Type(N->getRawType()),1046IsDefault(N->isDefault()), Value(N->getValue()) {}10471048bool isKeyOf(const DITemplateValueParameter *RHS) const {1049return Tag == RHS->getTag() && Name == RHS->getRawName() &&1050Type == RHS->getRawType() && IsDefault == RHS->isDefault() &&1051Value == RHS->getValue();1052}10531054unsigned getHashValue() const {1055return hash_combine(Tag, Name, Type, IsDefault, Value);1056}1057};10581059template <> struct MDNodeKeyImpl<DIGlobalVariable> {1060Metadata *Scope;1061MDString *Name;1062MDString *LinkageName;1063Metadata *File;1064unsigned Line;1065Metadata *Type;1066bool IsLocalToUnit;1067bool IsDefinition;1068Metadata *StaticDataMemberDeclaration;1069Metadata *TemplateParams;1070uint32_t AlignInBits;1071Metadata *Annotations;10721073MDNodeKeyImpl(Metadata *Scope, MDString *Name, MDString *LinkageName,1074Metadata *File, unsigned Line, Metadata *Type,1075bool IsLocalToUnit, bool IsDefinition,1076Metadata *StaticDataMemberDeclaration, Metadata *TemplateParams,1077uint32_t AlignInBits, Metadata *Annotations)1078: Scope(Scope), Name(Name), LinkageName(LinkageName), File(File),1079Line(Line), Type(Type), IsLocalToUnit(IsLocalToUnit),1080IsDefinition(IsDefinition),1081StaticDataMemberDeclaration(StaticDataMemberDeclaration),1082TemplateParams(TemplateParams), AlignInBits(AlignInBits),1083Annotations(Annotations) {}1084MDNodeKeyImpl(const DIGlobalVariable *N)1085: Scope(N->getRawScope()), Name(N->getRawName()),1086LinkageName(N->getRawLinkageName()), File(N->getRawFile()),1087Line(N->getLine()), Type(N->getRawType()),1088IsLocalToUnit(N->isLocalToUnit()), IsDefinition(N->isDefinition()),1089StaticDataMemberDeclaration(N->getRawStaticDataMemberDeclaration()),1090TemplateParams(N->getRawTemplateParams()),1091AlignInBits(N->getAlignInBits()), Annotations(N->getRawAnnotations()) {}10921093bool isKeyOf(const DIGlobalVariable *RHS) const {1094return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&1095LinkageName == RHS->getRawLinkageName() &&1096File == RHS->getRawFile() && Line == RHS->getLine() &&1097Type == RHS->getRawType() && IsLocalToUnit == RHS->isLocalToUnit() &&1098IsDefinition == RHS->isDefinition() &&1099StaticDataMemberDeclaration ==1100RHS->getRawStaticDataMemberDeclaration() &&1101TemplateParams == RHS->getRawTemplateParams() &&1102AlignInBits == RHS->getAlignInBits() &&1103Annotations == RHS->getRawAnnotations();1104}11051106unsigned getHashValue() const {1107// We do not use AlignInBits in hashing function here on purpose:1108// in most cases this param for local variable is zero (for function param1109// it is always zero). This leads to lots of hash collisions and errors on1110// cases with lots of similar variables.1111// clang/test/CodeGen/debug-info-257-args.c is an example of this problem,1112// generated IR is random for each run and test fails with Align included.1113// TODO: make hashing work fine with such situations1114return hash_combine(Scope, Name, LinkageName, File, Line, Type,1115IsLocalToUnit, IsDefinition, /* AlignInBits, */1116StaticDataMemberDeclaration, Annotations);1117}1118};11191120template <> struct MDNodeKeyImpl<DILocalVariable> {1121Metadata *Scope;1122MDString *Name;1123Metadata *File;1124unsigned Line;1125Metadata *Type;1126unsigned Arg;1127unsigned Flags;1128uint32_t AlignInBits;1129Metadata *Annotations;11301131MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line,1132Metadata *Type, unsigned Arg, unsigned Flags,1133uint32_t AlignInBits, Metadata *Annotations)1134: Scope(Scope), Name(Name), File(File), Line(Line), Type(Type), Arg(Arg),1135Flags(Flags), AlignInBits(AlignInBits), Annotations(Annotations) {}1136MDNodeKeyImpl(const DILocalVariable *N)1137: Scope(N->getRawScope()), Name(N->getRawName()), File(N->getRawFile()),1138Line(N->getLine()), Type(N->getRawType()), Arg(N->getArg()),1139Flags(N->getFlags()), AlignInBits(N->getAlignInBits()),1140Annotations(N->getRawAnnotations()) {}11411142bool isKeyOf(const DILocalVariable *RHS) const {1143return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&1144File == RHS->getRawFile() && Line == RHS->getLine() &&1145Type == RHS->getRawType() && Arg == RHS->getArg() &&1146Flags == RHS->getFlags() && AlignInBits == RHS->getAlignInBits() &&1147Annotations == RHS->getRawAnnotations();1148}11491150unsigned getHashValue() const {1151// We do not use AlignInBits in hashing function here on purpose:1152// in most cases this param for local variable is zero (for function param1153// it is always zero). This leads to lots of hash collisions and errors on1154// cases with lots of similar variables.1155// clang/test/CodeGen/debug-info-257-args.c is an example of this problem,1156// generated IR is random for each run and test fails with Align included.1157// TODO: make hashing work fine with such situations1158return hash_combine(Scope, Name, File, Line, Type, Arg, Flags, Annotations);1159}1160};11611162template <> struct MDNodeKeyImpl<DILabel> {1163Metadata *Scope;1164MDString *Name;1165Metadata *File;1166unsigned Line;11671168MDNodeKeyImpl(Metadata *Scope, MDString *Name, Metadata *File, unsigned Line)1169: Scope(Scope), Name(Name), File(File), Line(Line) {}1170MDNodeKeyImpl(const DILabel *N)1171: Scope(N->getRawScope()), Name(N->getRawName()), File(N->getRawFile()),1172Line(N->getLine()) {}11731174bool isKeyOf(const DILabel *RHS) const {1175return Scope == RHS->getRawScope() && Name == RHS->getRawName() &&1176File == RHS->getRawFile() && Line == RHS->getLine();1177}11781179/// Using name and line to get hash value. It should already be mostly unique.1180unsigned getHashValue() const { return hash_combine(Scope, Name, Line); }1181};11821183template <> struct MDNodeKeyImpl<DIExpression> {1184ArrayRef<uint64_t> Elements;11851186MDNodeKeyImpl(ArrayRef<uint64_t> Elements) : Elements(Elements) {}1187MDNodeKeyImpl(const DIExpression *N) : Elements(N->getElements()) {}11881189bool isKeyOf(const DIExpression *RHS) const {1190return Elements == RHS->getElements();1191}11921193unsigned getHashValue() const {1194return hash_combine_range(Elements.begin(), Elements.end());1195}1196};11971198template <> struct MDNodeKeyImpl<DIGlobalVariableExpression> {1199Metadata *Variable;1200Metadata *Expression;12011202MDNodeKeyImpl(Metadata *Variable, Metadata *Expression)1203: Variable(Variable), Expression(Expression) {}1204MDNodeKeyImpl(const DIGlobalVariableExpression *N)1205: Variable(N->getRawVariable()), Expression(N->getRawExpression()) {}12061207bool isKeyOf(const DIGlobalVariableExpression *RHS) const {1208return Variable == RHS->getRawVariable() &&1209Expression == RHS->getRawExpression();1210}12111212unsigned getHashValue() const { return hash_combine(Variable, Expression); }1213};12141215template <> struct MDNodeKeyImpl<DIObjCProperty> {1216MDString *Name;1217Metadata *File;1218unsigned Line;1219MDString *GetterName;1220MDString *SetterName;1221unsigned Attributes;1222Metadata *Type;12231224MDNodeKeyImpl(MDString *Name, Metadata *File, unsigned Line,1225MDString *GetterName, MDString *SetterName, unsigned Attributes,1226Metadata *Type)1227: Name(Name), File(File), Line(Line), GetterName(GetterName),1228SetterName(SetterName), Attributes(Attributes), Type(Type) {}1229MDNodeKeyImpl(const DIObjCProperty *N)1230: Name(N->getRawName()), File(N->getRawFile()), Line(N->getLine()),1231GetterName(N->getRawGetterName()), SetterName(N->getRawSetterName()),1232Attributes(N->getAttributes()), Type(N->getRawType()) {}12331234bool isKeyOf(const DIObjCProperty *RHS) const {1235return Name == RHS->getRawName() && File == RHS->getRawFile() &&1236Line == RHS->getLine() && GetterName == RHS->getRawGetterName() &&1237SetterName == RHS->getRawSetterName() &&1238Attributes == RHS->getAttributes() && Type == RHS->getRawType();1239}12401241unsigned getHashValue() const {1242return hash_combine(Name, File, Line, GetterName, SetterName, Attributes,1243Type);1244}1245};12461247template <> struct MDNodeKeyImpl<DIImportedEntity> {1248unsigned Tag;1249Metadata *Scope;1250Metadata *Entity;1251Metadata *File;1252unsigned Line;1253MDString *Name;1254Metadata *Elements;12551256MDNodeKeyImpl(unsigned Tag, Metadata *Scope, Metadata *Entity, Metadata *File,1257unsigned Line, MDString *Name, Metadata *Elements)1258: Tag(Tag), Scope(Scope), Entity(Entity), File(File), Line(Line),1259Name(Name), Elements(Elements) {}1260MDNodeKeyImpl(const DIImportedEntity *N)1261: Tag(N->getTag()), Scope(N->getRawScope()), Entity(N->getRawEntity()),1262File(N->getRawFile()), Line(N->getLine()), Name(N->getRawName()),1263Elements(N->getRawElements()) {}12641265bool isKeyOf(const DIImportedEntity *RHS) const {1266return Tag == RHS->getTag() && Scope == RHS->getRawScope() &&1267Entity == RHS->getRawEntity() && File == RHS->getFile() &&1268Line == RHS->getLine() && Name == RHS->getRawName() &&1269Elements == RHS->getRawElements();1270}12711272unsigned getHashValue() const {1273return hash_combine(Tag, Scope, Entity, File, Line, Name, Elements);1274}1275};12761277template <> struct MDNodeKeyImpl<DIMacro> {1278unsigned MIType;1279unsigned Line;1280MDString *Name;1281MDString *Value;12821283MDNodeKeyImpl(unsigned MIType, unsigned Line, MDString *Name, MDString *Value)1284: MIType(MIType), Line(Line), Name(Name), Value(Value) {}1285MDNodeKeyImpl(const DIMacro *N)1286: MIType(N->getMacinfoType()), Line(N->getLine()), Name(N->getRawName()),1287Value(N->getRawValue()) {}12881289bool isKeyOf(const DIMacro *RHS) const {1290return MIType == RHS->getMacinfoType() && Line == RHS->getLine() &&1291Name == RHS->getRawName() && Value == RHS->getRawValue();1292}12931294unsigned getHashValue() const {1295return hash_combine(MIType, Line, Name, Value);1296}1297};12981299template <> struct MDNodeKeyImpl<DIMacroFile> {1300unsigned MIType;1301unsigned Line;1302Metadata *File;1303Metadata *Elements;13041305MDNodeKeyImpl(unsigned MIType, unsigned Line, Metadata *File,1306Metadata *Elements)1307: MIType(MIType), Line(Line), File(File), Elements(Elements) {}1308MDNodeKeyImpl(const DIMacroFile *N)1309: MIType(N->getMacinfoType()), Line(N->getLine()), File(N->getRawFile()),1310Elements(N->getRawElements()) {}13111312bool isKeyOf(const DIMacroFile *RHS) const {1313return MIType == RHS->getMacinfoType() && Line == RHS->getLine() &&1314File == RHS->getRawFile() && Elements == RHS->getRawElements();1315}13161317unsigned getHashValue() const {1318return hash_combine(MIType, Line, File, Elements);1319}1320};13211322// DIArgLists are not MDNodes, but we still want to unique them in a DenseSet1323// based on a hash of their arguments.1324struct DIArgListKeyInfo {1325ArrayRef<ValueAsMetadata *> Args;13261327DIArgListKeyInfo(ArrayRef<ValueAsMetadata *> Args) : Args(Args) {}1328DIArgListKeyInfo(const DIArgList *N) : Args(N->getArgs()) {}13291330bool isKeyOf(const DIArgList *RHS) const { return Args == RHS->getArgs(); }13311332unsigned getHashValue() const {1333return hash_combine_range(Args.begin(), Args.end());1334}1335};13361337/// DenseMapInfo for DIArgList.1338struct DIArgListInfo {1339using KeyTy = DIArgListKeyInfo;13401341static inline DIArgList *getEmptyKey() {1342return DenseMapInfo<DIArgList *>::getEmptyKey();1343}13441345static inline DIArgList *getTombstoneKey() {1346return DenseMapInfo<DIArgList *>::getTombstoneKey();1347}13481349static unsigned getHashValue(const KeyTy &Key) { return Key.getHashValue(); }13501351static unsigned getHashValue(const DIArgList *N) {1352return KeyTy(N).getHashValue();1353}13541355static bool isEqual(const KeyTy &LHS, const DIArgList *RHS) {1356if (RHS == getEmptyKey() || RHS == getTombstoneKey())1357return false;1358return LHS.isKeyOf(RHS);1359}13601361static bool isEqual(const DIArgList *LHS, const DIArgList *RHS) {1362return LHS == RHS;1363}1364};13651366/// DenseMapInfo for MDNode subclasses.1367template <class NodeTy> struct MDNodeInfo {1368using KeyTy = MDNodeKeyImpl<NodeTy>;1369using SubsetEqualTy = MDNodeSubsetEqualImpl<NodeTy>;13701371static inline NodeTy *getEmptyKey() {1372return DenseMapInfo<NodeTy *>::getEmptyKey();1373}13741375static inline NodeTy *getTombstoneKey() {1376return DenseMapInfo<NodeTy *>::getTombstoneKey();1377}13781379static unsigned getHashValue(const KeyTy &Key) { return Key.getHashValue(); }13801381static unsigned getHashValue(const NodeTy *N) {1382return KeyTy(N).getHashValue();1383}13841385static bool isEqual(const KeyTy &LHS, const NodeTy *RHS) {1386if (RHS == getEmptyKey() || RHS == getTombstoneKey())1387return false;1388return SubsetEqualTy::isSubsetEqual(LHS, RHS) || LHS.isKeyOf(RHS);1389}13901391static bool isEqual(const NodeTy *LHS, const NodeTy *RHS) {1392if (LHS == RHS)1393return true;1394if (RHS == getEmptyKey() || RHS == getTombstoneKey())1395return false;1396return SubsetEqualTy::isSubsetEqual(LHS, RHS);1397}1398};13991400#define HANDLE_MDNODE_LEAF(CLASS) using CLASS##Info = MDNodeInfo<CLASS>;1401#include "llvm/IR/Metadata.def"14021403/// Multimap-like storage for metadata attachments.1404class MDAttachments {1405public:1406struct Attachment {1407unsigned MDKind;1408TrackingMDNodeRef Node;1409};14101411private:1412SmallVector<Attachment, 1> Attachments;14131414public:1415bool empty() const { return Attachments.empty(); }1416size_t size() const { return Attachments.size(); }14171418/// Returns the first attachment with the given ID or nullptr if no such1419/// attachment exists.1420MDNode *lookup(unsigned ID) const;14211422/// Appends all attachments with the given ID to \c Result in insertion order.1423/// If the global has no attachments with the given ID, or if ID is invalid,1424/// leaves Result unchanged.1425void get(unsigned ID, SmallVectorImpl<MDNode *> &Result) const;14261427/// Appends all attachments for the global to \c Result, sorting by attachment1428/// ID. Attachments with the same ID appear in insertion order. This function1429/// does \em not clear \c Result.1430void getAll(SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const;14311432/// Set an attachment to a particular node.1433///1434/// Set the \c ID attachment to \c MD, replacing the current attachments at \c1435/// ID (if anyway).1436void set(unsigned ID, MDNode *MD);14371438/// Adds an attachment to a particular node.1439void insert(unsigned ID, MDNode &MD);14401441/// Remove attachments with the given ID.1442///1443/// Remove the attachments at \c ID, if any.1444bool erase(unsigned ID);14451446/// Erase matching attachments.1447///1448/// Erases all attachments matching the \c shouldRemove predicate.1449template <class PredTy> void remove_if(PredTy shouldRemove) {1450llvm::erase_if(Attachments, shouldRemove);1451}1452};14531454class LLVMContextImpl {1455public:1456/// OwnedModules - The set of modules instantiated in this context, and which1457/// will be automatically deleted if this context is deleted.1458SmallPtrSet<Module *, 4> OwnedModules;14591460/// MachineFunctionNums - Keep the next available unique number available for1461/// a MachineFunction in given module. Module must in OwnedModules.1462DenseMap<Module *, unsigned> MachineFunctionNums;14631464/// The main remark streamer used by all the other streamers (e.g. IR, MIR,1465/// frontends, etc.). This should only be used by the specific streamers, and1466/// never directly.1467std::unique_ptr<remarks::RemarkStreamer> MainRemarkStreamer;14681469std::unique_ptr<DiagnosticHandler> DiagHandler;1470bool RespectDiagnosticFilters = false;1471bool DiagnosticsHotnessRequested = false;1472/// The minimum hotness value a diagnostic needs in order to be included in1473/// optimization diagnostics.1474///1475/// The threshold is an Optional value, which maps to one of the 3 states:1476/// 1). 0 => threshold disabled. All emarks will be printed.1477/// 2). positive int => manual threshold by user. Remarks with hotness exceed1478/// threshold will be printed.1479/// 3). None => 'auto' threshold by user. The actual value is not1480/// available at command line, but will be synced with1481/// hotness threhold from profile summary during1482/// compilation.1483///1484/// State 1 and 2 are considered as terminal states. State transition is1485/// only allowed from 3 to 2, when the threshold is first synced with profile1486/// summary. This ensures that the threshold is set only once and stays1487/// constant.1488///1489/// If threshold option is not specified, it is disabled (0) by default.1490std::optional<uint64_t> DiagnosticsHotnessThreshold = 0;14911492/// The percentage of difference between profiling branch weights and1493/// llvm.expect branch weights to tolerate when emiting MisExpect diagnostics1494std::optional<uint32_t> DiagnosticsMisExpectTolerance = 0;1495bool MisExpectWarningRequested = false;14961497/// The specialized remark streamer used by LLVM's OptimizationRemarkEmitter.1498std::unique_ptr<LLVMRemarkStreamer> LLVMRS;14991500LLVMContext::YieldCallbackTy YieldCallback = nullptr;1501void *YieldOpaqueHandle = nullptr;15021503DenseMap<const Value *, ValueName *> ValueNames;15041505DenseMap<unsigned, std::unique_ptr<ConstantInt>> IntZeroConstants;1506DenseMap<unsigned, std::unique_ptr<ConstantInt>> IntOneConstants;1507DenseMap<APInt, std::unique_ptr<ConstantInt>> IntConstants;1508DenseMap<std::pair<ElementCount, APInt>, std::unique_ptr<ConstantInt>>1509IntSplatConstants;15101511DenseMap<APFloat, std::unique_ptr<ConstantFP>> FPConstants;1512DenseMap<std::pair<ElementCount, APFloat>, std::unique_ptr<ConstantFP>>1513FPSplatConstants;15141515FoldingSet<AttributeImpl> AttrsSet;1516FoldingSet<AttributeListImpl> AttrsLists;1517FoldingSet<AttributeSetNode> AttrsSetNodes;15181519StringMap<MDString, BumpPtrAllocator> MDStringCache;1520DenseMap<Value *, ValueAsMetadata *> ValuesAsMetadata;1521DenseMap<Metadata *, MetadataAsValue *> MetadataAsValues;1522DenseSet<DIArgList *, DIArgListInfo> DIArgLists;15231524#define HANDLE_MDNODE_LEAF_UNIQUABLE(CLASS) \1525DenseSet<CLASS *, CLASS##Info> CLASS##s;1526#include "llvm/IR/Metadata.def"15271528// Optional map for looking up composite types by identifier.1529std::optional<DenseMap<const MDString *, DICompositeType *>> DITypeMap;15301531// MDNodes may be uniqued or not uniqued. When they're not uniqued, they1532// aren't in the MDNodeSet, but they're still shared between objects, so no1533// one object can destroy them. Keep track of them here so we can delete1534// them on context teardown.1535std::vector<MDNode *> DistinctMDNodes;15361537// ConstantRangeListAttributeImpl is a TrailingObjects/ArrayRef of1538// ConstantRange. Since this is a dynamically sized class, it's not1539// possible to use SpecificBumpPtrAllocator. Instead, we use normal Alloc1540// for allocation and record all allocated pointers in this vector. In the1541// LLVMContext destructor, call the destuctors of everything in the vector.1542std::vector<ConstantRangeListAttributeImpl *> ConstantRangeListAttributes;15431544DenseMap<Type *, std::unique_ptr<ConstantAggregateZero>> CAZConstants;15451546using ArrayConstantsTy = ConstantUniqueMap<ConstantArray>;1547ArrayConstantsTy ArrayConstants;15481549using StructConstantsTy = ConstantUniqueMap<ConstantStruct>;1550StructConstantsTy StructConstants;15511552using VectorConstantsTy = ConstantUniqueMap<ConstantVector>;1553VectorConstantsTy VectorConstants;15541555DenseMap<PointerType *, std::unique_ptr<ConstantPointerNull>> CPNConstants;15561557DenseMap<TargetExtType *, std::unique_ptr<ConstantTargetNone>> CTNConstants;15581559DenseMap<Type *, std::unique_ptr<UndefValue>> UVConstants;15601561DenseMap<Type *, std::unique_ptr<PoisonValue>> PVConstants;15621563StringMap<std::unique_ptr<ConstantDataSequential>> CDSConstants;15641565DenseMap<std::pair<const Function *, const BasicBlock *>, BlockAddress *>1566BlockAddresses;15671568DenseMap<const GlobalValue *, DSOLocalEquivalent *> DSOLocalEquivalents;15691570DenseMap<const GlobalValue *, NoCFIValue *> NoCFIValues;15711572ConstantUniqueMap<ConstantPtrAuth> ConstantPtrAuths;15731574ConstantUniqueMap<ConstantExpr> ExprConstants;15751576ConstantUniqueMap<InlineAsm> InlineAsms;15771578ConstantInt *TheTrueVal = nullptr;1579ConstantInt *TheFalseVal = nullptr;15801581// Basic type instances.1582Type VoidTy, LabelTy, HalfTy, BFloatTy, FloatTy, DoubleTy, MetadataTy,1583TokenTy;1584Type X86_FP80Ty, FP128Ty, PPC_FP128Ty, X86_MMXTy, X86_AMXTy;1585IntegerType Int1Ty, Int8Ty, Int16Ty, Int32Ty, Int64Ty, Int128Ty;15861587std::unique_ptr<ConstantTokenNone> TheNoneToken;15881589BumpPtrAllocator Alloc;1590UniqueStringSaver Saver{Alloc};1591SpecificBumpPtrAllocator<ConstantRangeAttributeImpl>1592ConstantRangeAttributeAlloc;15931594DenseMap<unsigned, IntegerType *> IntegerTypes;15951596using FunctionTypeSet = DenseSet<FunctionType *, FunctionTypeKeyInfo>;1597FunctionTypeSet FunctionTypes;1598using StructTypeSet = DenseSet<StructType *, AnonStructTypeKeyInfo>;1599StructTypeSet AnonStructTypes;1600StringMap<StructType *> NamedStructTypes;1601unsigned NamedStructTypesUniqueID = 0;16021603using TargetExtTypeSet = DenseSet<TargetExtType *, TargetExtTypeKeyInfo>;1604TargetExtTypeSet TargetExtTypes;16051606DenseMap<std::pair<Type *, uint64_t>, ArrayType *> ArrayTypes;1607DenseMap<std::pair<Type *, ElementCount>, VectorType *> VectorTypes;1608PointerType *AS0PointerType = nullptr; // AddrSpace = 01609DenseMap<unsigned, PointerType *> PointerTypes;1610DenseMap<std::pair<Type *, unsigned>, PointerType *> LegacyPointerTypes;1611DenseMap<std::pair<Type *, unsigned>, TypedPointerType *> ASTypedPointerTypes;16121613/// ValueHandles - This map keeps track of all of the value handles that are1614/// watching a Value*. The Value::HasValueHandle bit is used to know1615/// whether or not a value has an entry in this map.1616using ValueHandlesTy = DenseMap<Value *, ValueHandleBase *>;1617ValueHandlesTy ValueHandles;16181619/// CustomMDKindNames - Map to hold the metadata string to ID mapping.1620StringMap<unsigned> CustomMDKindNames;16211622/// Collection of metadata used in this context.1623DenseMap<const Value *, MDAttachments> ValueMetadata;16241625/// Map DIAssignID -> Instructions with that attachment.1626/// Managed by Instruction via Instruction::updateDIAssignIDMapping.1627/// Query using the at:: functions defined in DebugInfo.h.1628DenseMap<DIAssignID *, SmallVector<Instruction *, 1>> AssignmentIDToInstrs;16291630/// Collection of per-GlobalObject sections used in this context.1631DenseMap<const GlobalObject *, StringRef> GlobalObjectSections;16321633/// Collection of per-GlobalValue partitions used in this context.1634DenseMap<const GlobalValue *, StringRef> GlobalValuePartitions;16351636DenseMap<const GlobalValue *, GlobalValue::SanitizerMetadata>1637GlobalValueSanitizerMetadata;16381639/// DiscriminatorTable - This table maps file:line locations to an1640/// integer representing the next DWARF path discriminator to assign to1641/// instructions in different blocks at the same location.1642DenseMap<std::pair<const char *, unsigned>, unsigned> DiscriminatorTable;16431644/// A set of interned tags for operand bundles. The StringMap maps1645/// bundle tags to their IDs.1646///1647/// \see LLVMContext::getOperandBundleTagID1648StringMap<uint32_t> BundleTagCache;16491650StringMapEntry<uint32_t> *getOrInsertBundleTag(StringRef Tag);1651void getOperandBundleTags(SmallVectorImpl<StringRef> &Tags) const;1652uint32_t getOperandBundleTagID(StringRef Tag) const;16531654/// A set of interned synchronization scopes. The StringMap maps1655/// synchronization scope names to their respective synchronization scope IDs.1656StringMap<SyncScope::ID> SSC;16571658/// getOrInsertSyncScopeID - Maps synchronization scope name to1659/// synchronization scope ID. Every synchronization scope registered with1660/// LLVMContext has unique ID except pre-defined ones.1661SyncScope::ID getOrInsertSyncScopeID(StringRef SSN);16621663/// getSyncScopeNames - Populates client supplied SmallVector with1664/// synchronization scope names registered with LLVMContext. Synchronization1665/// scope names are ordered by increasing synchronization scope IDs.1666void getSyncScopeNames(SmallVectorImpl<StringRef> &SSNs) const;16671668/// Maintain the GC name for each function.1669///1670/// This saves allocating an additional word in Function for programs which1671/// do not use GC (i.e., most programs) at the cost of increased overhead for1672/// clients which do use GC.1673DenseMap<const Function *, std::string> GCNames;16741675/// Flag to indicate if Value (other than GlobalValue) retains their name or1676/// not.1677bool DiscardValueNames = false;16781679LLVMContextImpl(LLVMContext &C);1680~LLVMContextImpl();16811682/// Destroy the ConstantArrays if they are not used.1683void dropTriviallyDeadConstantArrays();16841685mutable OptPassGate *OPG = nullptr;16861687/// Access the object which can disable optional passes and individual1688/// optimizations at compile time.1689OptPassGate &getOptPassGate() const;16901691/// Set the object which can disable optional passes and individual1692/// optimizations at compile time.1693///1694/// The lifetime of the object must be guaranteed to extend as long as the1695/// LLVMContext is used by compilation.1696void setOptPassGate(OptPassGate &);16971698/// Mapping of blocks to collections of "trailing" DbgVariableRecords. As part1699/// of the "RemoveDIs" project, debug-info variable location records are going1700/// to cease being instructions... which raises the problem of where should1701/// they be recorded when we remove the terminator of a blocks, such as:1702///1703/// %foo = add i32 0, 01704/// br label %bar1705///1706/// If the branch is removed, a legitimate transient state while editing a1707/// block, any debug-records between those two instructions will not have a1708/// location. Each block thus records any DbgVariableRecord records that1709/// "trail" in such a way. These are stored in LLVMContext because typically1710/// LLVM only edits a small number of blocks at a time, so there's no need to1711/// bloat BasicBlock with such a data structure.1712SmallDenseMap<BasicBlock *, DbgMarker *> TrailingDbgRecords;17131714// Set, get and delete operations for TrailingDbgRecords.1715void setTrailingDbgRecords(BasicBlock *B, DbgMarker *M) {1716assert(!TrailingDbgRecords.count(B));1717TrailingDbgRecords[B] = M;1718}17191720DbgMarker *getTrailingDbgRecords(BasicBlock *B) {1721return TrailingDbgRecords.lookup(B);1722}17231724void deleteTrailingDbgRecords(BasicBlock *B) { TrailingDbgRecords.erase(B); }17251726std::string DefaultTargetCPU;1727std::string DefaultTargetFeatures;1728};17291730} // end namespace llvm17311732#endif // LLVM_LIB_IR_LLVMCONTEXTIMPL_H173317341735