1 //===-- llvm/Operator.h - Operator utility subclass -------------*- 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 classes for working with Instructions and 10 // ConstantExprs. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_IR_OPERATOR_H 15 #define LLVM_IR_OPERATOR_H 16 17 #include "llvm/ADT/None.h" 18 #include "llvm/ADT/Optional.h" 19 #include "llvm/IR/Constants.h" 20 #include "llvm/IR/Instruction.h" 21 #include "llvm/IR/Type.h" 22 #include "llvm/IR/Value.h" 23 #include "llvm/Support/Casting.h" 24 #include <cstddef> 25 26 namespace llvm { 27 28 /// This is a utility class that provides an abstraction for the common 29 /// functionality between Instructions and ConstantExprs. 30 class Operator : public User { 31 public: 32 // The Operator class is intended to be used as a utility, and is never itself 33 // instantiated. 34 Operator() = delete; 35 ~Operator() = delete; 36 37 void *operator new(size_t s) = delete; 38 39 /// Return the opcode for this Instruction or ConstantExpr. getOpcode()40 unsigned getOpcode() const { 41 if (const Instruction *I = dyn_cast<Instruction>(this)) 42 return I->getOpcode(); 43 return cast<ConstantExpr>(this)->getOpcode(); 44 } 45 46 /// If V is an Instruction or ConstantExpr, return its opcode. 47 /// Otherwise return UserOp1. getOpcode(const Value * V)48 static unsigned getOpcode(const Value *V) { 49 if (const Instruction *I = dyn_cast<Instruction>(V)) 50 return I->getOpcode(); 51 if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) 52 return CE->getOpcode(); 53 return Instruction::UserOp1; 54 } 55 classof(const Instruction *)56 static bool classof(const Instruction *) { return true; } classof(const ConstantExpr *)57 static bool classof(const ConstantExpr *) { return true; } classof(const Value * V)58 static bool classof(const Value *V) { 59 return isa<Instruction>(V) || isa<ConstantExpr>(V); 60 } 61 }; 62 63 /// Utility class for integer operators which may exhibit overflow - Add, Sub, 64 /// Mul, and Shl. It does not include SDiv, despite that operator having the 65 /// potential for overflow. 66 class OverflowingBinaryOperator : public Operator { 67 public: 68 enum { 69 AnyWrap = 0, 70 NoUnsignedWrap = (1 << 0), 71 NoSignedWrap = (1 << 1) 72 }; 73 74 private: 75 friend class Instruction; 76 friend class ConstantExpr; 77 setHasNoUnsignedWrap(bool B)78 void setHasNoUnsignedWrap(bool B) { 79 SubclassOptionalData = 80 (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap); 81 } setHasNoSignedWrap(bool B)82 void setHasNoSignedWrap(bool B) { 83 SubclassOptionalData = 84 (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap); 85 } 86 87 public: 88 /// Test whether this operation is known to never 89 /// undergo unsigned overflow, aka the nuw property. hasNoUnsignedWrap()90 bool hasNoUnsignedWrap() const { 91 return SubclassOptionalData & NoUnsignedWrap; 92 } 93 94 /// Test whether this operation is known to never 95 /// undergo signed overflow, aka the nsw property. hasNoSignedWrap()96 bool hasNoSignedWrap() const { 97 return (SubclassOptionalData & NoSignedWrap) != 0; 98 } 99 classof(const Instruction * I)100 static bool classof(const Instruction *I) { 101 return I->getOpcode() == Instruction::Add || 102 I->getOpcode() == Instruction::Sub || 103 I->getOpcode() == Instruction::Mul || 104 I->getOpcode() == Instruction::Shl; 105 } classof(const ConstantExpr * CE)106 static bool classof(const ConstantExpr *CE) { 107 return CE->getOpcode() == Instruction::Add || 108 CE->getOpcode() == Instruction::Sub || 109 CE->getOpcode() == Instruction::Mul || 110 CE->getOpcode() == Instruction::Shl; 111 } classof(const Value * V)112 static bool classof(const Value *V) { 113 return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || 114 (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); 115 } 116 }; 117 118 /// A udiv or sdiv instruction, which can be marked as "exact", 119 /// indicating that no bits are destroyed. 120 class PossiblyExactOperator : public Operator { 121 public: 122 enum { 123 IsExact = (1 << 0) 124 }; 125 126 private: 127 friend class Instruction; 128 friend class ConstantExpr; 129 setIsExact(bool B)130 void setIsExact(bool B) { 131 SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact); 132 } 133 134 public: 135 /// Test whether this division is known to be exact, with zero remainder. isExact()136 bool isExact() const { 137 return SubclassOptionalData & IsExact; 138 } 139 isPossiblyExactOpcode(unsigned OpC)140 static bool isPossiblyExactOpcode(unsigned OpC) { 141 return OpC == Instruction::SDiv || 142 OpC == Instruction::UDiv || 143 OpC == Instruction::AShr || 144 OpC == Instruction::LShr; 145 } 146 classof(const ConstantExpr * CE)147 static bool classof(const ConstantExpr *CE) { 148 return isPossiblyExactOpcode(CE->getOpcode()); 149 } classof(const Instruction * I)150 static bool classof(const Instruction *I) { 151 return isPossiblyExactOpcode(I->getOpcode()); 152 } classof(const Value * V)153 static bool classof(const Value *V) { 154 return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || 155 (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); 156 } 157 }; 158 159 /// Convenience struct for specifying and reasoning about fast-math flags. 160 class FastMathFlags { 161 private: 162 friend class FPMathOperator; 163 164 unsigned Flags = 0; 165 FastMathFlags(unsigned F)166 FastMathFlags(unsigned F) { 167 // If all 7 bits are set, turn this into -1. If the number of bits grows, 168 // this must be updated. This is intended to provide some forward binary 169 // compatibility insurance for the meaning of 'fast' in case bits are added. 170 if (F == 0x7F) Flags = ~0U; 171 else Flags = F; 172 } 173 174 public: 175 // This is how the bits are used in Value::SubclassOptionalData so they 176 // should fit there too. 177 // WARNING: We're out of space. SubclassOptionalData only has 7 bits. New 178 // functionality will require a change in how this information is stored. 179 enum { 180 AllowReassoc = (1 << 0), 181 NoNaNs = (1 << 1), 182 NoInfs = (1 << 2), 183 NoSignedZeros = (1 << 3), 184 AllowReciprocal = (1 << 4), 185 AllowContract = (1 << 5), 186 ApproxFunc = (1 << 6) 187 }; 188 189 FastMathFlags() = default; 190 getFast()191 static FastMathFlags getFast() { 192 FastMathFlags FMF; 193 FMF.setFast(); 194 return FMF; 195 } 196 any()197 bool any() const { return Flags != 0; } none()198 bool none() const { return Flags == 0; } all()199 bool all() const { return Flags == ~0U; } 200 clear()201 void clear() { Flags = 0; } set()202 void set() { Flags = ~0U; } 203 204 /// Flag queries allowReassoc()205 bool allowReassoc() const { return 0 != (Flags & AllowReassoc); } noNaNs()206 bool noNaNs() const { return 0 != (Flags & NoNaNs); } noInfs()207 bool noInfs() const { return 0 != (Flags & NoInfs); } noSignedZeros()208 bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); } allowReciprocal()209 bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); } allowContract()210 bool allowContract() const { return 0 != (Flags & AllowContract); } approxFunc()211 bool approxFunc() const { return 0 != (Flags & ApproxFunc); } 212 /// 'Fast' means all bits are set. isFast()213 bool isFast() const { return all(); } 214 215 /// Flag setters 216 void setAllowReassoc(bool B = true) { 217 Flags = (Flags & ~AllowReassoc) | B * AllowReassoc; 218 } 219 void setNoNaNs(bool B = true) { 220 Flags = (Flags & ~NoNaNs) | B * NoNaNs; 221 } 222 void setNoInfs(bool B = true) { 223 Flags = (Flags & ~NoInfs) | B * NoInfs; 224 } 225 void setNoSignedZeros(bool B = true) { 226 Flags = (Flags & ~NoSignedZeros) | B * NoSignedZeros; 227 } 228 void setAllowReciprocal(bool B = true) { 229 Flags = (Flags & ~AllowReciprocal) | B * AllowReciprocal; 230 } 231 void setAllowContract(bool B = true) { 232 Flags = (Flags & ~AllowContract) | B * AllowContract; 233 } 234 void setApproxFunc(bool B = true) { 235 Flags = (Flags & ~ApproxFunc) | B * ApproxFunc; 236 } 237 void setFast(bool B = true) { B ? set() : clear(); } 238 239 void operator&=(const FastMathFlags &OtherFlags) { 240 Flags &= OtherFlags.Flags; 241 } 242 void operator|=(const FastMathFlags &OtherFlags) { 243 Flags |= OtherFlags.Flags; 244 } 245 }; 246 247 /// Utility class for floating point operations which can have 248 /// information about relaxed accuracy requirements attached to them. 249 class FPMathOperator : public Operator { 250 private: 251 friend class Instruction; 252 253 /// 'Fast' means all bits are set. setFast(bool B)254 void setFast(bool B) { 255 setHasAllowReassoc(B); 256 setHasNoNaNs(B); 257 setHasNoInfs(B); 258 setHasNoSignedZeros(B); 259 setHasAllowReciprocal(B); 260 setHasAllowContract(B); 261 setHasApproxFunc(B); 262 } 263 setHasAllowReassoc(bool B)264 void setHasAllowReassoc(bool B) { 265 SubclassOptionalData = 266 (SubclassOptionalData & ~FastMathFlags::AllowReassoc) | 267 (B * FastMathFlags::AllowReassoc); 268 } 269 setHasNoNaNs(bool B)270 void setHasNoNaNs(bool B) { 271 SubclassOptionalData = 272 (SubclassOptionalData & ~FastMathFlags::NoNaNs) | 273 (B * FastMathFlags::NoNaNs); 274 } 275 setHasNoInfs(bool B)276 void setHasNoInfs(bool B) { 277 SubclassOptionalData = 278 (SubclassOptionalData & ~FastMathFlags::NoInfs) | 279 (B * FastMathFlags::NoInfs); 280 } 281 setHasNoSignedZeros(bool B)282 void setHasNoSignedZeros(bool B) { 283 SubclassOptionalData = 284 (SubclassOptionalData & ~FastMathFlags::NoSignedZeros) | 285 (B * FastMathFlags::NoSignedZeros); 286 } 287 setHasAllowReciprocal(bool B)288 void setHasAllowReciprocal(bool B) { 289 SubclassOptionalData = 290 (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) | 291 (B * FastMathFlags::AllowReciprocal); 292 } 293 setHasAllowContract(bool B)294 void setHasAllowContract(bool B) { 295 SubclassOptionalData = 296 (SubclassOptionalData & ~FastMathFlags::AllowContract) | 297 (B * FastMathFlags::AllowContract); 298 } 299 setHasApproxFunc(bool B)300 void setHasApproxFunc(bool B) { 301 SubclassOptionalData = 302 (SubclassOptionalData & ~FastMathFlags::ApproxFunc) | 303 (B * FastMathFlags::ApproxFunc); 304 } 305 306 /// Convenience function for setting multiple fast-math flags. 307 /// FMF is a mask of the bits to set. setFastMathFlags(FastMathFlags FMF)308 void setFastMathFlags(FastMathFlags FMF) { 309 SubclassOptionalData |= FMF.Flags; 310 } 311 312 /// Convenience function for copying all fast-math flags. 313 /// All values in FMF are transferred to this operator. copyFastMathFlags(FastMathFlags FMF)314 void copyFastMathFlags(FastMathFlags FMF) { 315 SubclassOptionalData = FMF.Flags; 316 } 317 318 public: 319 /// Test if this operation allows all non-strict floating-point transforms. isFast()320 bool isFast() const { 321 return ((SubclassOptionalData & FastMathFlags::AllowReassoc) != 0 && 322 (SubclassOptionalData & FastMathFlags::NoNaNs) != 0 && 323 (SubclassOptionalData & FastMathFlags::NoInfs) != 0 && 324 (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0 && 325 (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0 && 326 (SubclassOptionalData & FastMathFlags::AllowContract) != 0 && 327 (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0); 328 } 329 330 /// Test if this operation may be simplified with reassociative transforms. hasAllowReassoc()331 bool hasAllowReassoc() const { 332 return (SubclassOptionalData & FastMathFlags::AllowReassoc) != 0; 333 } 334 335 /// Test if this operation's arguments and results are assumed not-NaN. hasNoNaNs()336 bool hasNoNaNs() const { 337 return (SubclassOptionalData & FastMathFlags::NoNaNs) != 0; 338 } 339 340 /// Test if this operation's arguments and results are assumed not-infinite. hasNoInfs()341 bool hasNoInfs() const { 342 return (SubclassOptionalData & FastMathFlags::NoInfs) != 0; 343 } 344 345 /// Test if this operation can ignore the sign of zero. hasNoSignedZeros()346 bool hasNoSignedZeros() const { 347 return (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0; 348 } 349 350 /// Test if this operation can use reciprocal multiply instead of division. hasAllowReciprocal()351 bool hasAllowReciprocal() const { 352 return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0; 353 } 354 355 /// Test if this operation can be floating-point contracted (FMA). hasAllowContract()356 bool hasAllowContract() const { 357 return (SubclassOptionalData & FastMathFlags::AllowContract) != 0; 358 } 359 360 /// Test if this operation allows approximations of math library functions or 361 /// intrinsics. hasApproxFunc()362 bool hasApproxFunc() const { 363 return (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0; 364 } 365 366 /// Convenience function for getting all the fast-math flags getFastMathFlags()367 FastMathFlags getFastMathFlags() const { 368 return FastMathFlags(SubclassOptionalData); 369 } 370 371 /// Get the maximum error permitted by this operation in ULPs. An accuracy of 372 /// 0.0 means that the operation should be performed with the default 373 /// precision. 374 float getFPAccuracy() const; 375 classof(const Value * V)376 static bool classof(const Value *V) { 377 unsigned Opcode; 378 if (auto *I = dyn_cast<Instruction>(V)) 379 Opcode = I->getOpcode(); 380 else if (auto *CE = dyn_cast<ConstantExpr>(V)) 381 Opcode = CE->getOpcode(); 382 else 383 return false; 384 385 switch (Opcode) { 386 case Instruction::FNeg: 387 case Instruction::FAdd: 388 case Instruction::FSub: 389 case Instruction::FMul: 390 case Instruction::FDiv: 391 case Instruction::FRem: 392 // FIXME: To clean up and correct the semantics of fast-math-flags, FCmp 393 // should not be treated as a math op, but the other opcodes should. 394 // This would make things consistent with Select/PHI (FP value type 395 // determines whether they are math ops and, therefore, capable of 396 // having fast-math-flags). 397 case Instruction::FCmp: 398 return true; 399 case Instruction::PHI: 400 case Instruction::Select: 401 case Instruction::Call: { 402 Type *Ty = V->getType(); 403 while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) 404 Ty = ArrTy->getElementType(); 405 return Ty->isFPOrFPVectorTy(); 406 } 407 default: 408 return false; 409 } 410 } 411 }; 412 413 /// A helper template for defining operators for individual opcodes. 414 template<typename SuperClass, unsigned Opc> 415 class ConcreteOperator : public SuperClass { 416 public: classof(const Instruction * I)417 static bool classof(const Instruction *I) { 418 return I->getOpcode() == Opc; 419 } classof(const ConstantExpr * CE)420 static bool classof(const ConstantExpr *CE) { 421 return CE->getOpcode() == Opc; 422 } classof(const Value * V)423 static bool classof(const Value *V) { 424 return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || 425 (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); 426 } 427 }; 428 429 class AddOperator 430 : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> { 431 }; 432 class SubOperator 433 : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> { 434 }; 435 class MulOperator 436 : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> { 437 }; 438 class ShlOperator 439 : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> { 440 }; 441 442 class SDivOperator 443 : public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> { 444 }; 445 class UDivOperator 446 : public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> { 447 }; 448 class AShrOperator 449 : public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> { 450 }; 451 class LShrOperator 452 : public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> { 453 }; 454 455 class ZExtOperator : public ConcreteOperator<Operator, Instruction::ZExt> {}; 456 457 class GEPOperator 458 : public ConcreteOperator<Operator, Instruction::GetElementPtr> { 459 friend class GetElementPtrInst; 460 friend class ConstantExpr; 461 462 enum { 463 IsInBounds = (1 << 0), 464 // InRangeIndex: bits 1-6 465 }; 466 setIsInBounds(bool B)467 void setIsInBounds(bool B) { 468 SubclassOptionalData = 469 (SubclassOptionalData & ~IsInBounds) | (B * IsInBounds); 470 } 471 472 public: 473 /// Test whether this is an inbounds GEP, as defined by LangRef.html. isInBounds()474 bool isInBounds() const { 475 return SubclassOptionalData & IsInBounds; 476 } 477 478 /// Returns the offset of the index with an inrange attachment, or None if 479 /// none. getInRangeIndex()480 Optional<unsigned> getInRangeIndex() const { 481 if (SubclassOptionalData >> 1 == 0) return None; 482 return (SubclassOptionalData >> 1) - 1; 483 } 484 idx_begin()485 inline op_iterator idx_begin() { return op_begin()+1; } idx_begin()486 inline const_op_iterator idx_begin() const { return op_begin()+1; } idx_end()487 inline op_iterator idx_end() { return op_end(); } idx_end()488 inline const_op_iterator idx_end() const { return op_end(); } 489 getPointerOperand()490 Value *getPointerOperand() { 491 return getOperand(0); 492 } getPointerOperand()493 const Value *getPointerOperand() const { 494 return getOperand(0); 495 } getPointerOperandIndex()496 static unsigned getPointerOperandIndex() { 497 return 0U; // get index for modifying correct operand 498 } 499 500 /// Method to return the pointer operand as a PointerType. getPointerOperandType()501 Type *getPointerOperandType() const { 502 return getPointerOperand()->getType(); 503 } 504 505 Type *getSourceElementType() const; 506 Type *getResultElementType() const; 507 508 /// Method to return the address space of the pointer operand. getPointerAddressSpace()509 unsigned getPointerAddressSpace() const { 510 return getPointerOperandType()->getPointerAddressSpace(); 511 } 512 getNumIndices()513 unsigned getNumIndices() const { // Note: always non-negative 514 return getNumOperands() - 1; 515 } 516 hasIndices()517 bool hasIndices() const { 518 return getNumOperands() > 1; 519 } 520 521 /// Return true if all of the indices of this GEP are zeros. 522 /// If so, the result pointer and the first operand have the same 523 /// value, just potentially different types. hasAllZeroIndices()524 bool hasAllZeroIndices() const { 525 for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { 526 if (ConstantInt *C = dyn_cast<ConstantInt>(I)) 527 if (C->isZero()) 528 continue; 529 return false; 530 } 531 return true; 532 } 533 534 /// Return true if all of the indices of this GEP are constant integers. 535 /// If so, the result pointer and the first operand have 536 /// a constant offset between them. hasAllConstantIndices()537 bool hasAllConstantIndices() const { 538 for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { 539 if (!isa<ConstantInt>(I)) 540 return false; 541 } 542 return true; 543 } 544 countNonConstantIndices()545 unsigned countNonConstantIndices() const { 546 return count_if(make_range(idx_begin(), idx_end()), [](const Use& use) { 547 return !isa<ConstantInt>(*use); 548 }); 549 } 550 551 /// Compute the maximum alignment that this GEP is garranteed to preserve. 552 Align getMaxPreservedAlignment(const DataLayout &DL) const; 553 554 /// Accumulate the constant address offset of this GEP if possible. 555 /// 556 /// This routine accepts an APInt into which it will try to accumulate the 557 /// constant offset of this GEP. 558 /// 559 /// If \p ExternalAnalysis is provided it will be used to calculate a offset 560 /// when a operand of GEP is not constant. 561 /// For example, for a value \p ExternalAnalysis might try to calculate a 562 /// lower bound. If \p ExternalAnalysis is successful, it should return true. 563 /// 564 /// If the \p ExternalAnalysis returns false or the value returned by \p 565 /// ExternalAnalysis results in a overflow/underflow, this routine returns 566 /// false and the value of the offset APInt is undefined (it is *not* 567 /// preserved!). 568 /// 569 /// The APInt passed into this routine must be at exactly as wide as the 570 /// IntPtr type for the address space of the base GEP pointer. 571 bool accumulateConstantOffset( 572 const DataLayout &DL, APInt &Offset, 573 function_ref<bool(Value &, APInt &)> ExternalAnalysis = nullptr) const; 574 575 static bool accumulateConstantOffset( 576 Type *SourceType, ArrayRef<const Value *> Index, const DataLayout &DL, 577 APInt &Offset, 578 function_ref<bool(Value &, APInt &)> ExternalAnalysis = nullptr); 579 580 /// Collect the offset of this GEP as a map of Values to their associated 581 /// APInt multipliers, as well as a total Constant Offset. 582 bool collectOffset(const DataLayout &DL, unsigned BitWidth, 583 SmallDenseMap<Value *, APInt, 8> &VariableOffsets, 584 APInt &ConstantOffset) const; 585 }; 586 587 class PtrToIntOperator 588 : public ConcreteOperator<Operator, Instruction::PtrToInt> { 589 friend class PtrToInt; 590 friend class ConstantExpr; 591 592 public: getPointerOperand()593 Value *getPointerOperand() { 594 return getOperand(0); 595 } getPointerOperand()596 const Value *getPointerOperand() const { 597 return getOperand(0); 598 } 599 getPointerOperandIndex()600 static unsigned getPointerOperandIndex() { 601 return 0U; // get index for modifying correct operand 602 } 603 604 /// Method to return the pointer operand as a PointerType. getPointerOperandType()605 Type *getPointerOperandType() const { 606 return getPointerOperand()->getType(); 607 } 608 609 /// Method to return the address space of the pointer operand. getPointerAddressSpace()610 unsigned getPointerAddressSpace() const { 611 return cast<PointerType>(getPointerOperandType())->getAddressSpace(); 612 } 613 }; 614 615 class BitCastOperator 616 : public ConcreteOperator<Operator, Instruction::BitCast> { 617 friend class BitCastInst; 618 friend class ConstantExpr; 619 620 public: getSrcTy()621 Type *getSrcTy() const { 622 return getOperand(0)->getType(); 623 } 624 getDestTy()625 Type *getDestTy() const { 626 return getType(); 627 } 628 }; 629 630 class AddrSpaceCastOperator 631 : public ConcreteOperator<Operator, Instruction::AddrSpaceCast> { 632 friend class AddrSpaceCastInst; 633 friend class ConstantExpr; 634 635 public: getPointerOperand()636 Value *getPointerOperand() { return getOperand(0); } 637 getPointerOperand()638 const Value *getPointerOperand() const { return getOperand(0); } 639 getSrcAddressSpace()640 unsigned getSrcAddressSpace() const { 641 return getPointerOperand()->getType()->getPointerAddressSpace(); 642 } 643 getDestAddressSpace()644 unsigned getDestAddressSpace() const { 645 return getType()->getPointerAddressSpace(); 646 } 647 }; 648 649 } // end namespace llvm 650 651 #endif // LLVM_IR_OPERATOR_H 652