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