xref: /freebsd/contrib/llvm-project/llvm/lib/IR/ConstantsContext.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===-- ConstantsContext.h - Constants-related Context Interals -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 //  This file defines various helper methods and classes used by
10 // LLVMContextImpl for creating and managing constants.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_LIB_IR_CONSTANTSCONTEXT_H
15 #define LLVM_LIB_IR_CONSTANTSCONTEXT_H
16 
17 #include "llvm/ADT/ArrayRef.h"
18 #include "llvm/ADT/DenseMapInfo.h"
19 #include "llvm/ADT/DenseSet.h"
20 #include "llvm/ADT/Hashing.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringRef.h"
23 #include "llvm/IR/Constant.h"
24 #include "llvm/IR/Constants.h"
25 #include "llvm/IR/DerivedTypes.h"
26 #include "llvm/IR/GlobalVariable.h"
27 #include "llvm/IR/InlineAsm.h"
28 #include "llvm/IR/Instruction.h"
29 #include "llvm/IR/Instructions.h"
30 #include "llvm/IR/OperandTraits.h"
31 #include "llvm/Support/Casting.h"
32 #include "llvm/Support/Debug.h"
33 #include "llvm/Support/ErrorHandling.h"
34 #include "llvm/Support/raw_ostream.h"
35 #include <cassert>
36 #include <cstddef>
37 #include <cstdint>
38 #include <utility>
39 
40 #define DEBUG_TYPE "ir"
41 
42 namespace llvm {
43 
44 /// CastConstantExpr - This class is private to Constants.cpp, and is used
45 /// behind the scenes to implement cast constant exprs.
46 class CastConstantExpr final : public ConstantExpr {
47 public:
CastConstantExpr(unsigned Opcode,Constant * C,Type * Ty)48   CastConstantExpr(unsigned Opcode, Constant *C, Type *Ty)
49     : ConstantExpr(Ty, Opcode, &Op<0>(), 1) {
50     Op<0>() = C;
51   }
52 
53   // allocate space for exactly one operand
new(size_t S)54   void *operator new(size_t S) { return User::operator new(S, 1); }
delete(void * Ptr)55   void operator delete(void *Ptr) { User::operator delete(Ptr); }
56 
57   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
58 
classof(const ConstantExpr * CE)59   static bool classof(const ConstantExpr *CE) {
60     return Instruction::isCast(CE->getOpcode());
61   }
classof(const Value * V)62   static bool classof(const Value *V) {
63     return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
64   }
65 };
66 
67 /// BinaryConstantExpr - This class is private to Constants.cpp, and is used
68 /// behind the scenes to implement binary constant exprs.
69 class BinaryConstantExpr final : public ConstantExpr {
70 public:
BinaryConstantExpr(unsigned Opcode,Constant * C1,Constant * C2,unsigned Flags)71   BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2,
72                      unsigned Flags)
73     : ConstantExpr(C1->getType(), Opcode, &Op<0>(), 2) {
74     Op<0>() = C1;
75     Op<1>() = C2;
76     SubclassOptionalData = Flags;
77   }
78 
79   // allocate space for exactly two operands
new(size_t S)80   void *operator new(size_t S) { return User::operator new(S, 2); }
delete(void * Ptr)81   void operator delete(void *Ptr) { User::operator delete(Ptr); }
82 
83   /// Transparently provide more efficient getOperand methods.
84   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
85 
classof(const ConstantExpr * CE)86   static bool classof(const ConstantExpr *CE) {
87     return Instruction::isBinaryOp(CE->getOpcode());
88   }
classof(const Value * V)89   static bool classof(const Value *V) {
90     return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
91   }
92 };
93 
94 /// ExtractElementConstantExpr - This class is private to
95 /// Constants.cpp, and is used behind the scenes to implement
96 /// extractelement constant exprs.
97 class ExtractElementConstantExpr final : public ConstantExpr {
98 public:
ExtractElementConstantExpr(Constant * C1,Constant * C2)99   ExtractElementConstantExpr(Constant *C1, Constant *C2)
100     : ConstantExpr(cast<VectorType>(C1->getType())->getElementType(),
101                    Instruction::ExtractElement, &Op<0>(), 2) {
102     Op<0>() = C1;
103     Op<1>() = C2;
104   }
105 
106   // allocate space for exactly two operands
new(size_t S)107   void *operator new(size_t S) { return User::operator new(S, 2); }
delete(void * Ptr)108   void operator delete(void *Ptr) { User::operator delete(Ptr); }
109 
110   /// Transparently provide more efficient getOperand methods.
111   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
112 
classof(const ConstantExpr * CE)113   static bool classof(const ConstantExpr *CE) {
114     return CE->getOpcode() == Instruction::ExtractElement;
115   }
classof(const Value * V)116   static bool classof(const Value *V) {
117     return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
118   }
119 };
120 
121 /// InsertElementConstantExpr - This class is private to
122 /// Constants.cpp, and is used behind the scenes to implement
123 /// insertelement constant exprs.
124 class InsertElementConstantExpr final : public ConstantExpr {
125 public:
InsertElementConstantExpr(Constant * C1,Constant * C2,Constant * C3)126   InsertElementConstantExpr(Constant *C1, Constant *C2, Constant *C3)
127     : ConstantExpr(C1->getType(), Instruction::InsertElement,
128                    &Op<0>(), 3) {
129     Op<0>() = C1;
130     Op<1>() = C2;
131     Op<2>() = C3;
132   }
133 
134   // allocate space for exactly three operands
new(size_t S)135   void *operator new(size_t S) { return User::operator new(S, 3); }
delete(void * Ptr)136   void operator delete(void *Ptr) { User::operator delete(Ptr); }
137 
138   /// Transparently provide more efficient getOperand methods.
139   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
140 
classof(const ConstantExpr * CE)141   static bool classof(const ConstantExpr *CE) {
142     return CE->getOpcode() == Instruction::InsertElement;
143   }
classof(const Value * V)144   static bool classof(const Value *V) {
145     return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
146   }
147 };
148 
149 /// ShuffleVectorConstantExpr - This class is private to
150 /// Constants.cpp, and is used behind the scenes to implement
151 /// shufflevector constant exprs.
152 class ShuffleVectorConstantExpr final : public ConstantExpr {
153 public:
ShuffleVectorConstantExpr(Constant * C1,Constant * C2,ArrayRef<int> Mask)154   ShuffleVectorConstantExpr(Constant *C1, Constant *C2, ArrayRef<int> Mask)
155       : ConstantExpr(VectorType::get(
156                          cast<VectorType>(C1->getType())->getElementType(),
157                          Mask.size(), isa<ScalableVectorType>(C1->getType())),
158                      Instruction::ShuffleVector, &Op<0>(), 2) {
159     assert(ShuffleVectorInst::isValidOperands(C1, C2, Mask) &&
160            "Invalid shuffle vector instruction operands!");
161     Op<0>() = C1;
162     Op<1>() = C2;
163     ShuffleMask.assign(Mask.begin(), Mask.end());
164     ShuffleMaskForBitcode =
165         ShuffleVectorInst::convertShuffleMaskForBitcode(Mask, getType());
166   }
167 
168   SmallVector<int, 4> ShuffleMask;
169   Constant *ShuffleMaskForBitcode;
170 
new(size_t S)171   void *operator new(size_t S) { return User::operator new(S, 2); }
delete(void * Ptr)172   void operator delete(void *Ptr) { return User::operator delete(Ptr); }
173 
174   /// Transparently provide more efficient getOperand methods.
175   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
176 
classof(const ConstantExpr * CE)177   static bool classof(const ConstantExpr *CE) {
178     return CE->getOpcode() == Instruction::ShuffleVector;
179   }
classof(const Value * V)180   static bool classof(const Value *V) {
181     return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
182   }
183 };
184 
185 /// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
186 /// used behind the scenes to implement getelementptr constant exprs.
187 class GetElementPtrConstantExpr : public ConstantExpr {
188   Type *SrcElementTy;
189   Type *ResElementTy;
190   std::optional<ConstantRange> InRange;
191 
192   GetElementPtrConstantExpr(Type *SrcElementTy, Constant *C,
193                             ArrayRef<Constant *> IdxList, Type *DestTy,
194                             std::optional<ConstantRange> InRange);
195 
196 public:
197   static GetElementPtrConstantExpr *
Create(Type * SrcElementTy,Constant * C,ArrayRef<Constant * > IdxList,Type * DestTy,unsigned Flags,std::optional<ConstantRange> InRange)198   Create(Type *SrcElementTy, Constant *C, ArrayRef<Constant *> IdxList,
199          Type *DestTy, unsigned Flags, std::optional<ConstantRange> InRange) {
200     GetElementPtrConstantExpr *Result = new (IdxList.size() + 1)
201         GetElementPtrConstantExpr(SrcElementTy, C, IdxList, DestTy,
202                                   std::move(InRange));
203     Result->SubclassOptionalData = Flags;
204     return Result;
205   }
206 
207   Type *getSourceElementType() const;
208   Type *getResultElementType() const;
209   std::optional<ConstantRange> getInRange() const;
210 
211   /// Transparently provide more efficient getOperand methods.
212   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
213 
classof(const ConstantExpr * CE)214   static bool classof(const ConstantExpr *CE) {
215     return CE->getOpcode() == Instruction::GetElementPtr;
216   }
classof(const Value * V)217   static bool classof(const Value *V) {
218     return isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V));
219   }
220 };
221 
222 template <>
223 struct OperandTraits<CastConstantExpr>
224     : public FixedNumOperandTraits<CastConstantExpr, 1> {};
225 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CastConstantExpr, Value)
226 
227 template <>
228 struct OperandTraits<BinaryConstantExpr>
229     : public FixedNumOperandTraits<BinaryConstantExpr, 2> {};
230 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(BinaryConstantExpr, Value)
231 
232 template <>
233 struct OperandTraits<ExtractElementConstantExpr>
234     : public FixedNumOperandTraits<ExtractElementConstantExpr, 2> {};
235 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ExtractElementConstantExpr, Value)
236 
237 template <>
238 struct OperandTraits<InsertElementConstantExpr>
239     : public FixedNumOperandTraits<InsertElementConstantExpr, 3> {};
240 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(InsertElementConstantExpr, Value)
241 
242 template <>
243 struct OperandTraits<ShuffleVectorConstantExpr>
244     : public FixedNumOperandTraits<ShuffleVectorConstantExpr, 2> {};
245 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ShuffleVectorConstantExpr, Value)
246 
247 template <>
248 struct OperandTraits<GetElementPtrConstantExpr>
249     : public VariadicOperandTraits<GetElementPtrConstantExpr, 1> {};
250 
251 DEFINE_TRANSPARENT_OPERAND_ACCESSORS(GetElementPtrConstantExpr, Value)
252 
253 template <class ConstantClass> struct ConstantAggrKeyType;
254 struct InlineAsmKeyType;
255 struct ConstantExprKeyType;
256 struct ConstantPtrAuthKeyType;
257 
258 template <class ConstantClass> struct ConstantInfo;
259 template <> struct ConstantInfo<ConstantExpr> {
260   using ValType = ConstantExprKeyType;
261   using TypeClass = Type;
262 };
263 template <> struct ConstantInfo<InlineAsm> {
264   using ValType = InlineAsmKeyType;
265   using TypeClass = PointerType;
266 };
267 template <> struct ConstantInfo<ConstantArray> {
268   using ValType = ConstantAggrKeyType<ConstantArray>;
269   using TypeClass = ArrayType;
270 };
271 template <> struct ConstantInfo<ConstantStruct> {
272   using ValType = ConstantAggrKeyType<ConstantStruct>;
273   using TypeClass = StructType;
274 };
275 template <> struct ConstantInfo<ConstantVector> {
276   using ValType = ConstantAggrKeyType<ConstantVector>;
277   using TypeClass = VectorType;
278 };
279 template <> struct ConstantInfo<ConstantPtrAuth> {
280   using ValType = ConstantPtrAuthKeyType;
281   using TypeClass = Type;
282 };
283 
284 template <class ConstantClass> struct ConstantAggrKeyType {
285   ArrayRef<Constant *> Operands;
286 
287   ConstantAggrKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {}
288 
289   ConstantAggrKeyType(ArrayRef<Constant *> Operands, const ConstantClass *)
290       : Operands(Operands) {}
291 
292   ConstantAggrKeyType(const ConstantClass *C,
293                       SmallVectorImpl<Constant *> &Storage) {
294     assert(Storage.empty() && "Expected empty storage");
295     for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I)
296       Storage.push_back(C->getOperand(I));
297     Operands = Storage;
298   }
299 
300   bool operator==(const ConstantAggrKeyType &X) const {
301     return Operands == X.Operands;
302   }
303 
304   bool operator==(const ConstantClass *C) const {
305     if (Operands.size() != C->getNumOperands())
306       return false;
307     for (unsigned I = 0, E = Operands.size(); I != E; ++I)
308       if (Operands[I] != C->getOperand(I))
309         return false;
310     return true;
311   }
312 
313   unsigned getHash() const {
314     return hash_combine_range(Operands.begin(), Operands.end());
315   }
316 
317   using TypeClass = typename ConstantInfo<ConstantClass>::TypeClass;
318 
319   ConstantClass *create(TypeClass *Ty) const {
320     return new (Operands.size()) ConstantClass(Ty, Operands);
321   }
322 };
323 
324 struct InlineAsmKeyType {
325   StringRef AsmString;
326   StringRef Constraints;
327   FunctionType *FTy;
328   bool HasSideEffects;
329   bool IsAlignStack;
330   InlineAsm::AsmDialect AsmDialect;
331   bool CanThrow;
332 
333   InlineAsmKeyType(StringRef AsmString, StringRef Constraints,
334                    FunctionType *FTy, bool HasSideEffects, bool IsAlignStack,
335                    InlineAsm::AsmDialect AsmDialect, bool canThrow)
336       : AsmString(AsmString), Constraints(Constraints), FTy(FTy),
337         HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack),
338         AsmDialect(AsmDialect), CanThrow(canThrow) {}
339 
340   InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl<Constant *> &)
341       : AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()),
342         FTy(Asm->getFunctionType()), HasSideEffects(Asm->hasSideEffects()),
343         IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()),
344         CanThrow(Asm->canThrow()) {}
345 
346   bool operator==(const InlineAsmKeyType &X) const {
347     return HasSideEffects == X.HasSideEffects &&
348            IsAlignStack == X.IsAlignStack && AsmDialect == X.AsmDialect &&
349            AsmString == X.AsmString && Constraints == X.Constraints &&
350            FTy == X.FTy && CanThrow == X.CanThrow;
351   }
352 
353   bool operator==(const InlineAsm *Asm) const {
354     return HasSideEffects == Asm->hasSideEffects() &&
355            IsAlignStack == Asm->isAlignStack() &&
356            AsmDialect == Asm->getDialect() &&
357            AsmString == Asm->getAsmString() &&
358            Constraints == Asm->getConstraintString() &&
359            FTy == Asm->getFunctionType() && CanThrow == Asm->canThrow();
360   }
361 
362   unsigned getHash() const {
363     return hash_combine(AsmString, Constraints, HasSideEffects, IsAlignStack,
364                         AsmDialect, FTy, CanThrow);
365   }
366 
367   using TypeClass = ConstantInfo<InlineAsm>::TypeClass;
368 
369   InlineAsm *create(TypeClass *Ty) const {
370     assert(PointerType::getUnqual(FTy) == Ty);
371     return new InlineAsm(FTy, std::string(AsmString), std::string(Constraints),
372                          HasSideEffects, IsAlignStack, AsmDialect, CanThrow);
373   }
374 };
375 
376 struct ConstantExprKeyType {
377 private:
378   uint8_t Opcode;
379   uint8_t SubclassOptionalData;
380   ArrayRef<Constant *> Ops;
381   ArrayRef<int> ShuffleMask;
382   Type *ExplicitTy;
383   std::optional<ConstantRange> InRange;
384 
385   static ArrayRef<int> getShuffleMaskIfValid(const ConstantExpr *CE) {
386     if (CE->getOpcode() == Instruction::ShuffleVector)
387       return CE->getShuffleMask();
388     return std::nullopt;
389   }
390 
391   static Type *getSourceElementTypeIfValid(const ConstantExpr *CE) {
392     if (auto *GEPCE = dyn_cast<GetElementPtrConstantExpr>(CE))
393       return GEPCE->getSourceElementType();
394     return nullptr;
395   }
396 
397   static std::optional<ConstantRange>
398   getInRangeIfValid(const ConstantExpr *CE) {
399     if (auto *GEPCE = dyn_cast<GetElementPtrConstantExpr>(CE))
400       return GEPCE->getInRange();
401     return std::nullopt;
402   }
403 
404 public:
405   ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops,
406                       unsigned short SubclassOptionalData = 0,
407                       ArrayRef<int> ShuffleMask = std::nullopt,
408                       Type *ExplicitTy = nullptr,
409                       std::optional<ConstantRange> InRange = std::nullopt)
410       : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData), Ops(Ops),
411         ShuffleMask(ShuffleMask), ExplicitTy(ExplicitTy),
412         InRange(std::move(InRange)) {}
413 
414   ConstantExprKeyType(ArrayRef<Constant *> Operands, const ConstantExpr *CE)
415       : Opcode(CE->getOpcode()),
416         SubclassOptionalData(CE->getRawSubclassOptionalData()), Ops(Operands),
417         ShuffleMask(getShuffleMaskIfValid(CE)),
418         ExplicitTy(getSourceElementTypeIfValid(CE)),
419         InRange(getInRangeIfValid(CE)) {}
420 
421   ConstantExprKeyType(const ConstantExpr *CE,
422                       SmallVectorImpl<Constant *> &Storage)
423       : Opcode(CE->getOpcode()),
424         SubclassOptionalData(CE->getRawSubclassOptionalData()),
425         ShuffleMask(getShuffleMaskIfValid(CE)),
426         ExplicitTy(getSourceElementTypeIfValid(CE)),
427         InRange(getInRangeIfValid(CE)) {
428     assert(Storage.empty() && "Expected empty storage");
429     for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I)
430       Storage.push_back(CE->getOperand(I));
431     Ops = Storage;
432   }
433 
434   static bool rangesEqual(const std::optional<ConstantRange> &A,
435                           const std::optional<ConstantRange> &B) {
436     if (!A.has_value() || !B.has_value())
437       return A.has_value() == B.has_value();
438     return A->getBitWidth() == B->getBitWidth() && A == B;
439   }
440 
441   bool operator==(const ConstantExprKeyType &X) const {
442     return Opcode == X.Opcode &&
443            SubclassOptionalData == X.SubclassOptionalData && Ops == X.Ops &&
444            ShuffleMask == X.ShuffleMask && ExplicitTy == X.ExplicitTy &&
445            rangesEqual(InRange, X.InRange);
446   }
447 
448   bool operator==(const ConstantExpr *CE) const {
449     if (Opcode != CE->getOpcode())
450       return false;
451     if (SubclassOptionalData != CE->getRawSubclassOptionalData())
452       return false;
453     if (Ops.size() != CE->getNumOperands())
454       return false;
455     for (unsigned I = 0, E = Ops.size(); I != E; ++I)
456       if (Ops[I] != CE->getOperand(I))
457         return false;
458     if (ShuffleMask != getShuffleMaskIfValid(CE))
459       return false;
460     if (ExplicitTy != getSourceElementTypeIfValid(CE))
461       return false;
462     if (!rangesEqual(InRange, getInRangeIfValid(CE)))
463       return false;
464     return true;
465   }
466 
467   unsigned getHash() const {
468     return hash_combine(
469         Opcode, SubclassOptionalData,
470         hash_combine_range(Ops.begin(), Ops.end()),
471         hash_combine_range(ShuffleMask.begin(), ShuffleMask.end()), ExplicitTy);
472   }
473 
474   using TypeClass = ConstantInfo<ConstantExpr>::TypeClass;
475 
476   ConstantExpr *create(TypeClass *Ty) const {
477     switch (Opcode) {
478     default:
479       if (Instruction::isCast(Opcode))
480         return new CastConstantExpr(Opcode, Ops[0], Ty);
481       if ((Opcode >= Instruction::BinaryOpsBegin &&
482            Opcode < Instruction::BinaryOpsEnd))
483         return new BinaryConstantExpr(Opcode, Ops[0], Ops[1],
484                                       SubclassOptionalData);
485       llvm_unreachable("Invalid ConstantExpr!");
486     case Instruction::ExtractElement:
487       return new ExtractElementConstantExpr(Ops[0], Ops[1]);
488     case Instruction::InsertElement:
489       return new InsertElementConstantExpr(Ops[0], Ops[1], Ops[2]);
490     case Instruction::ShuffleVector:
491       return new ShuffleVectorConstantExpr(Ops[0], Ops[1], ShuffleMask);
492     case Instruction::GetElementPtr:
493       return GetElementPtrConstantExpr::Create(
494           ExplicitTy, Ops[0], Ops.slice(1), Ty, SubclassOptionalData, InRange);
495     }
496   }
497 };
498 
499 struct ConstantPtrAuthKeyType {
500   ArrayRef<Constant *> Operands;
501 
502   ConstantPtrAuthKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {}
503 
504   ConstantPtrAuthKeyType(ArrayRef<Constant *> Operands, const ConstantPtrAuth *)
505       : Operands(Operands) {}
506 
507   ConstantPtrAuthKeyType(const ConstantPtrAuth *C,
508                          SmallVectorImpl<Constant *> &Storage) {
509     assert(Storage.empty() && "Expected empty storage");
510     for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I)
511       Storage.push_back(cast<Constant>(C->getOperand(I)));
512     Operands = Storage;
513   }
514 
515   bool operator==(const ConstantPtrAuthKeyType &X) const {
516     return Operands == X.Operands;
517   }
518 
519   bool operator==(const ConstantPtrAuth *C) const {
520     if (Operands.size() != C->getNumOperands())
521       return false;
522     for (unsigned I = 0, E = Operands.size(); I != E; ++I)
523       if (Operands[I] != C->getOperand(I))
524         return false;
525     return true;
526   }
527 
528   unsigned getHash() const {
529     return hash_combine_range(Operands.begin(), Operands.end());
530   }
531 
532   using TypeClass = typename ConstantInfo<ConstantPtrAuth>::TypeClass;
533 
534   ConstantPtrAuth *create(TypeClass *Ty) const {
535     return new ConstantPtrAuth(Operands[0], cast<ConstantInt>(Operands[1]),
536                                cast<ConstantInt>(Operands[2]), Operands[3]);
537   }
538 };
539 
540 // Free memory for a given constant.  Assumes the constant has already been
541 // removed from all relevant maps.
542 void deleteConstant(Constant *C);
543 
544 template <class ConstantClass> class ConstantUniqueMap {
545 public:
546   using ValType = typename ConstantInfo<ConstantClass>::ValType;
547   using TypeClass = typename ConstantInfo<ConstantClass>::TypeClass;
548   using LookupKey = std::pair<TypeClass *, ValType>;
549 
550   /// Key and hash together, so that we compute the hash only once and reuse it.
551   using LookupKeyHashed = std::pair<unsigned, LookupKey>;
552 
553 private:
554   struct MapInfo {
555     using ConstantClassInfo = DenseMapInfo<ConstantClass *>;
556 
557     static inline ConstantClass *getEmptyKey() {
558       return ConstantClassInfo::getEmptyKey();
559     }
560 
561     static inline ConstantClass *getTombstoneKey() {
562       return ConstantClassInfo::getTombstoneKey();
563     }
564 
565     static unsigned getHashValue(const ConstantClass *CP) {
566       SmallVector<Constant *, 32> Storage;
567       return getHashValue(LookupKey(CP->getType(), ValType(CP, Storage)));
568     }
569 
570     static bool isEqual(const ConstantClass *LHS, const ConstantClass *RHS) {
571       return LHS == RHS;
572     }
573 
574     static unsigned getHashValue(const LookupKey &Val) {
575       return hash_combine(Val.first, Val.second.getHash());
576     }
577 
578     static unsigned getHashValue(const LookupKeyHashed &Val) {
579       return Val.first;
580     }
581 
582     static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) {
583       if (RHS == getEmptyKey() || RHS == getTombstoneKey())
584         return false;
585       if (LHS.first != RHS->getType())
586         return false;
587       return LHS.second == RHS;
588     }
589 
590     static bool isEqual(const LookupKeyHashed &LHS, const ConstantClass *RHS) {
591       return isEqual(LHS.second, RHS);
592     }
593   };
594 
595 public:
596   using MapTy = DenseSet<ConstantClass *, MapInfo>;
597 
598 private:
599   MapTy Map;
600 
601 public:
602   typename MapTy::iterator begin() { return Map.begin(); }
603   typename MapTy::iterator end() { return Map.end(); }
604 
605   void freeConstants() {
606     for (auto &I : Map)
607       deleteConstant(I);
608   }
609 
610 private:
611   ConstantClass *create(TypeClass *Ty, ValType V, LookupKeyHashed &HashKey) {
612     ConstantClass *Result = V.create(Ty);
613 
614     assert(Result->getType() == Ty && "Type specified is not correct!");
615     Map.insert_as(Result, HashKey);
616 
617     return Result;
618   }
619 
620 public:
621   /// Return the specified constant from the map, creating it if necessary.
622   ConstantClass *getOrCreate(TypeClass *Ty, ValType V) {
623     LookupKey Key(Ty, V);
624     /// Hash once, and reuse it for the lookup and the insertion if needed.
625     LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key);
626 
627     ConstantClass *Result = nullptr;
628 
629     auto I = Map.find_as(Lookup);
630     if (I == Map.end())
631       Result = create(Ty, V, Lookup);
632     else
633       Result = *I;
634     assert(Result && "Unexpected nullptr");
635 
636     return Result;
637   }
638 
639   /// Remove this constant from the map
640   void remove(ConstantClass *CP) {
641     typename MapTy::iterator I = Map.find(CP);
642     assert(I != Map.end() && "Constant not found in constant table!");
643     assert(*I == CP && "Didn't find correct element?");
644     Map.erase(I);
645   }
646 
647   ConstantClass *replaceOperandsInPlace(ArrayRef<Constant *> Operands,
648                                         ConstantClass *CP, Value *From,
649                                         Constant *To, unsigned NumUpdated = 0,
650                                         unsigned OperandNo = ~0u) {
651     LookupKey Key(CP->getType(), ValType(Operands, CP));
652     /// Hash once, and reuse it for the lookup and the insertion if needed.
653     LookupKeyHashed Lookup(MapInfo::getHashValue(Key), Key);
654 
655     auto ItMap = Map.find_as(Lookup);
656     if (ItMap != Map.end())
657       return *ItMap;
658 
659     // Update to the new value.  Optimize for the case when we have a single
660     // operand that we're changing, but handle bulk updates efficiently.
661     remove(CP);
662     if (NumUpdated == 1) {
663       assert(OperandNo < CP->getNumOperands() && "Invalid index");
664       assert(CP->getOperand(OperandNo) != To && "I didn't contain From!");
665       CP->setOperand(OperandNo, To);
666     } else {
667       for (unsigned I = 0, E = CP->getNumOperands(); I != E; ++I)
668         if (CP->getOperand(I) == From)
669           CP->setOperand(I, To);
670     }
671     Map.insert_as(CP, Lookup);
672     return nullptr;
673   }
674 
675   void dump() const {
676     LLVM_DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
677   }
678 };
679 
680 template <> inline void ConstantUniqueMap<InlineAsm>::freeConstants() {
681   for (auto &I : Map)
682     delete I;
683 }
684 
685 } // end namespace llvm
686 
687 #endif // LLVM_LIB_IR_CONSTANTSCONTEXT_H
688