1 //===-- llvm/IntrinsicInst.h - Intrinsic Instruction Wrappers ---*- 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 classes that make it really easy to deal with intrinsic 10 // functions with the isa/dyncast family of functions. In particular, this 11 // allows you to do things like: 12 // 13 // if (MemCpyInst *MCI = dyn_cast<MemCpyInst>(Inst)) 14 // ... MCI->getDest() ... MCI->getSource() ... 15 // 16 // All intrinsic function calls are instances of the call instruction, so these 17 // are all subclasses of the CallInst class. Note that none of these classes 18 // has state or virtual methods, which is an important part of this gross/neat 19 // hack working. 20 // 21 //===----------------------------------------------------------------------===// 22 23 #ifndef LLVM_IR_INTRINSICINST_H 24 #define LLVM_IR_INTRINSICINST_H 25 26 #include "llvm/IR/Constants.h" 27 #include "llvm/IR/DerivedTypes.h" 28 #include "llvm/IR/FPEnv.h" 29 #include "llvm/IR/Function.h" 30 #include "llvm/IR/GlobalVariable.h" 31 #include "llvm/IR/Instructions.h" 32 #include "llvm/IR/Intrinsics.h" 33 #include "llvm/IR/Metadata.h" 34 #include "llvm/IR/Value.h" 35 #include "llvm/Support/Casting.h" 36 #include <cassert> 37 #include <cstdint> 38 39 namespace llvm { 40 41 /// A wrapper class for inspecting calls to intrinsic functions. 42 /// This allows the standard isa/dyncast/cast functionality to work with calls 43 /// to intrinsic functions. 44 class IntrinsicInst : public CallInst { 45 public: 46 IntrinsicInst() = delete; 47 IntrinsicInst(const IntrinsicInst &) = delete; 48 IntrinsicInst &operator=(const IntrinsicInst &) = delete; 49 50 /// Return the intrinsic ID of this intrinsic. getIntrinsicID()51 Intrinsic::ID getIntrinsicID() const { 52 return getCalledFunction()->getIntrinsicID(); 53 } 54 55 // Methods for support type inquiry through isa, cast, and dyn_cast: classof(const CallInst * I)56 static bool classof(const CallInst *I) { 57 if (const Function *CF = I->getCalledFunction()) 58 return CF->isIntrinsic(); 59 return false; 60 } classof(const Value * V)61 static bool classof(const Value *V) { 62 return isa<CallInst>(V) && classof(cast<CallInst>(V)); 63 } 64 }; 65 66 /// This is the common base class for debug info intrinsics. 67 class DbgInfoIntrinsic : public IntrinsicInst { 68 public: 69 /// \name Casting methods 70 /// @{ classof(const IntrinsicInst * I)71 static bool classof(const IntrinsicInst *I) { 72 switch (I->getIntrinsicID()) { 73 case Intrinsic::dbg_declare: 74 case Intrinsic::dbg_value: 75 case Intrinsic::dbg_addr: 76 case Intrinsic::dbg_label: 77 return true; 78 default: return false; 79 } 80 } classof(const Value * V)81 static bool classof(const Value *V) { 82 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 83 } 84 /// @} 85 }; 86 87 /// This is the common base class for debug info intrinsics for variables. 88 class DbgVariableIntrinsic : public DbgInfoIntrinsic { 89 public: 90 /// Get the location corresponding to the variable referenced by the debug 91 /// info intrinsic. Depending on the intrinsic, this could be the 92 /// variable's value or its address. 93 Value *getVariableLocation(bool AllowNullOp = true) const; 94 95 /// Does this describe the address of a local variable. True for dbg.addr 96 /// and dbg.declare, but not dbg.value, which describes its value. isAddressOfVariable()97 bool isAddressOfVariable() const { 98 return getIntrinsicID() != Intrinsic::dbg_value; 99 } 100 getVariable()101 DILocalVariable *getVariable() const { 102 return cast<DILocalVariable>(getRawVariable()); 103 } 104 getExpression()105 DIExpression *getExpression() const { 106 return cast<DIExpression>(getRawExpression()); 107 } 108 getRawVariable()109 Metadata *getRawVariable() const { 110 return cast<MetadataAsValue>(getArgOperand(1))->getMetadata(); 111 } 112 getRawExpression()113 Metadata *getRawExpression() const { 114 return cast<MetadataAsValue>(getArgOperand(2))->getMetadata(); 115 } 116 117 /// Get the size (in bits) of the variable, or fragment of the variable that 118 /// is described. 119 Optional<uint64_t> getFragmentSizeInBits() const; 120 121 /// \name Casting methods 122 /// @{ classof(const IntrinsicInst * I)123 static bool classof(const IntrinsicInst *I) { 124 switch (I->getIntrinsicID()) { 125 case Intrinsic::dbg_declare: 126 case Intrinsic::dbg_value: 127 case Intrinsic::dbg_addr: 128 return true; 129 default: return false; 130 } 131 } classof(const Value * V)132 static bool classof(const Value *V) { 133 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 134 } 135 /// @} 136 }; 137 138 /// This represents the llvm.dbg.declare instruction. 139 class DbgDeclareInst : public DbgVariableIntrinsic { 140 public: getAddress()141 Value *getAddress() const { return getVariableLocation(); } 142 143 /// \name Casting methods 144 /// @{ classof(const IntrinsicInst * I)145 static bool classof(const IntrinsicInst *I) { 146 return I->getIntrinsicID() == Intrinsic::dbg_declare; 147 } classof(const Value * V)148 static bool classof(const Value *V) { 149 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 150 } 151 /// @} 152 }; 153 154 /// This represents the llvm.dbg.addr instruction. 155 class DbgAddrIntrinsic : public DbgVariableIntrinsic { 156 public: getAddress()157 Value *getAddress() const { return getVariableLocation(); } 158 159 /// \name Casting methods 160 /// @{ classof(const IntrinsicInst * I)161 static bool classof(const IntrinsicInst *I) { 162 return I->getIntrinsicID() == Intrinsic::dbg_addr; 163 } classof(const Value * V)164 static bool classof(const Value *V) { 165 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 166 } 167 }; 168 169 /// This represents the llvm.dbg.value instruction. 170 class DbgValueInst : public DbgVariableIntrinsic { 171 public: getValue()172 Value *getValue() const { 173 return getVariableLocation(/* AllowNullOp = */ false); 174 } 175 176 /// \name Casting methods 177 /// @{ classof(const IntrinsicInst * I)178 static bool classof(const IntrinsicInst *I) { 179 return I->getIntrinsicID() == Intrinsic::dbg_value; 180 } classof(const Value * V)181 static bool classof(const Value *V) { 182 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 183 } 184 /// @} 185 }; 186 187 /// This represents the llvm.dbg.label instruction. 188 class DbgLabelInst : public DbgInfoIntrinsic { 189 public: getLabel()190 DILabel *getLabel() const { 191 return cast<DILabel>(getRawLabel()); 192 } 193 getRawLabel()194 Metadata *getRawLabel() const { 195 return cast<MetadataAsValue>(getArgOperand(0))->getMetadata(); 196 } 197 198 /// Methods for support type inquiry through isa, cast, and dyn_cast: 199 /// @{ classof(const IntrinsicInst * I)200 static bool classof(const IntrinsicInst *I) { 201 return I->getIntrinsicID() == Intrinsic::dbg_label; 202 } classof(const Value * V)203 static bool classof(const Value *V) { 204 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 205 } 206 /// @} 207 }; 208 209 /// This is the common base class for constrained floating point intrinsics. 210 class ConstrainedFPIntrinsic : public IntrinsicInst { 211 public: 212 bool isUnaryOp() const; 213 bool isTernaryOp() const; 214 Optional<fp::RoundingMode> getRoundingMode() const; 215 Optional<fp::ExceptionBehavior> getExceptionBehavior() const; 216 217 // Methods for support type inquiry through isa, cast, and dyn_cast: 218 static bool classof(const IntrinsicInst *I); classof(const Value * V)219 static bool classof(const Value *V) { 220 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 221 } 222 }; 223 224 /// Constrained floating point compare intrinsics. 225 class ConstrainedFPCmpIntrinsic : public ConstrainedFPIntrinsic { 226 public: 227 FCmpInst::Predicate getPredicate() const; 228 229 // Methods for support type inquiry through isa, cast, and dyn_cast: classof(const IntrinsicInst * I)230 static bool classof(const IntrinsicInst *I) { 231 switch (I->getIntrinsicID()) { 232 case Intrinsic::experimental_constrained_fcmp: 233 case Intrinsic::experimental_constrained_fcmps: 234 return true; 235 default: return false; 236 } 237 } classof(const Value * V)238 static bool classof(const Value *V) { 239 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 240 } 241 }; 242 243 /// This class represents an intrinsic that is based on a binary operation. 244 /// This includes op.with.overflow and saturating add/sub intrinsics. 245 class BinaryOpIntrinsic : public IntrinsicInst { 246 public: classof(const IntrinsicInst * I)247 static bool classof(const IntrinsicInst *I) { 248 switch (I->getIntrinsicID()) { 249 case Intrinsic::uadd_with_overflow: 250 case Intrinsic::sadd_with_overflow: 251 case Intrinsic::usub_with_overflow: 252 case Intrinsic::ssub_with_overflow: 253 case Intrinsic::umul_with_overflow: 254 case Intrinsic::smul_with_overflow: 255 case Intrinsic::uadd_sat: 256 case Intrinsic::sadd_sat: 257 case Intrinsic::usub_sat: 258 case Intrinsic::ssub_sat: 259 return true; 260 default: 261 return false; 262 } 263 } classof(const Value * V)264 static bool classof(const Value *V) { 265 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 266 } 267 getLHS()268 Value *getLHS() const { return const_cast<Value*>(getArgOperand(0)); } getRHS()269 Value *getRHS() const { return const_cast<Value*>(getArgOperand(1)); } 270 271 /// Returns the binary operation underlying the intrinsic. 272 Instruction::BinaryOps getBinaryOp() const; 273 274 /// Whether the intrinsic is signed or unsigned. 275 bool isSigned() const; 276 277 /// Returns one of OBO::NoSignedWrap or OBO::NoUnsignedWrap. 278 unsigned getNoWrapKind() const; 279 }; 280 281 /// Represents an op.with.overflow intrinsic. 282 class WithOverflowInst : public BinaryOpIntrinsic { 283 public: classof(const IntrinsicInst * I)284 static bool classof(const IntrinsicInst *I) { 285 switch (I->getIntrinsicID()) { 286 case Intrinsic::uadd_with_overflow: 287 case Intrinsic::sadd_with_overflow: 288 case Intrinsic::usub_with_overflow: 289 case Intrinsic::ssub_with_overflow: 290 case Intrinsic::umul_with_overflow: 291 case Intrinsic::smul_with_overflow: 292 return true; 293 default: 294 return false; 295 } 296 } classof(const Value * V)297 static bool classof(const Value *V) { 298 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 299 } 300 }; 301 302 /// Represents a saturating add/sub intrinsic. 303 class SaturatingInst : public BinaryOpIntrinsic { 304 public: classof(const IntrinsicInst * I)305 static bool classof(const IntrinsicInst *I) { 306 switch (I->getIntrinsicID()) { 307 case Intrinsic::uadd_sat: 308 case Intrinsic::sadd_sat: 309 case Intrinsic::usub_sat: 310 case Intrinsic::ssub_sat: 311 return true; 312 default: 313 return false; 314 } 315 } classof(const Value * V)316 static bool classof(const Value *V) { 317 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 318 } 319 }; 320 321 /// Common base class for all memory intrinsics. Simply provides 322 /// common methods. 323 /// Written as CRTP to avoid a common base class amongst the 324 /// three atomicity hierarchies. 325 template <typename Derived> class MemIntrinsicBase : public IntrinsicInst { 326 private: 327 enum { ARG_DEST = 0, ARG_LENGTH = 2 }; 328 329 public: getRawDest()330 Value *getRawDest() const { 331 return const_cast<Value *>(getArgOperand(ARG_DEST)); 332 } getRawDestUse()333 const Use &getRawDestUse() const { return getArgOperandUse(ARG_DEST); } getRawDestUse()334 Use &getRawDestUse() { return getArgOperandUse(ARG_DEST); } 335 getLength()336 Value *getLength() const { 337 return const_cast<Value *>(getArgOperand(ARG_LENGTH)); 338 } getLengthUse()339 const Use &getLengthUse() const { return getArgOperandUse(ARG_LENGTH); } getLengthUse()340 Use &getLengthUse() { return getArgOperandUse(ARG_LENGTH); } 341 342 /// This is just like getRawDest, but it strips off any cast 343 /// instructions (including addrspacecast) that feed it, giving the 344 /// original input. The returned value is guaranteed to be a pointer. getDest()345 Value *getDest() const { return getRawDest()->stripPointerCasts(); } 346 getDestAddressSpace()347 unsigned getDestAddressSpace() const { 348 return cast<PointerType>(getRawDest()->getType())->getAddressSpace(); 349 } 350 351 /// FIXME: Remove this function once transition to Align is over. 352 /// Use getDestAlign() instead. getDestAlignment()353 unsigned getDestAlignment() const { return getParamAlignment(ARG_DEST); } getDestAlign()354 MaybeAlign getDestAlign() const { return getParamAlign(ARG_DEST); } 355 356 /// Set the specified arguments of the instruction. setDest(Value * Ptr)357 void setDest(Value *Ptr) { 358 assert(getRawDest()->getType() == Ptr->getType() && 359 "setDest called with pointer of wrong type!"); 360 setArgOperand(ARG_DEST, Ptr); 361 } 362 363 /// FIXME: Remove this function once transition to Align is over. 364 /// Use the version that takes MaybeAlign instead of this one. setDestAlignment(unsigned Alignment)365 void setDestAlignment(unsigned Alignment) { 366 setDestAlignment(MaybeAlign(Alignment)); 367 } setDestAlignment(MaybeAlign Alignment)368 void setDestAlignment(MaybeAlign Alignment) { 369 removeParamAttr(ARG_DEST, Attribute::Alignment); 370 if (Alignment) 371 addParamAttr(ARG_DEST, 372 Attribute::getWithAlignment(getContext(), *Alignment)); 373 } setDestAlignment(Align Alignment)374 void setDestAlignment(Align Alignment) { 375 removeParamAttr(ARG_DEST, Attribute::Alignment); 376 addParamAttr(ARG_DEST, 377 Attribute::getWithAlignment(getContext(), Alignment)); 378 } 379 setLength(Value * L)380 void setLength(Value *L) { 381 assert(getLength()->getType() == L->getType() && 382 "setLength called with value of wrong type!"); 383 setArgOperand(ARG_LENGTH, L); 384 } 385 }; 386 387 /// Common base class for all memory transfer intrinsics. Simply provides 388 /// common methods. 389 template <class BaseCL> class MemTransferBase : public BaseCL { 390 private: 391 enum { ARG_SOURCE = 1 }; 392 393 public: 394 /// Return the arguments to the instruction. getRawSource()395 Value *getRawSource() const { 396 return const_cast<Value *>(BaseCL::getArgOperand(ARG_SOURCE)); 397 } getRawSourceUse()398 const Use &getRawSourceUse() const { 399 return BaseCL::getArgOperandUse(ARG_SOURCE); 400 } getRawSourceUse()401 Use &getRawSourceUse() { return BaseCL::getArgOperandUse(ARG_SOURCE); } 402 403 /// This is just like getRawSource, but it strips off any cast 404 /// instructions that feed it, giving the original input. The returned 405 /// value is guaranteed to be a pointer. getSource()406 Value *getSource() const { return getRawSource()->stripPointerCasts(); } 407 getSourceAddressSpace()408 unsigned getSourceAddressSpace() const { 409 return cast<PointerType>(getRawSource()->getType())->getAddressSpace(); 410 } 411 412 /// FIXME: Remove this function once transition to Align is over. 413 /// Use getSourceAlign() instead. getSourceAlignment()414 unsigned getSourceAlignment() const { 415 return BaseCL::getParamAlignment(ARG_SOURCE); 416 } 417 getSourceAlign()418 MaybeAlign getSourceAlign() const { 419 return BaseCL::getParamAlign(ARG_SOURCE); 420 } 421 setSource(Value * Ptr)422 void setSource(Value *Ptr) { 423 assert(getRawSource()->getType() == Ptr->getType() && 424 "setSource called with pointer of wrong type!"); 425 BaseCL::setArgOperand(ARG_SOURCE, Ptr); 426 } 427 428 /// FIXME: Remove this function once transition to Align is over. 429 /// Use the version that takes MaybeAlign instead of this one. setSourceAlignment(unsigned Alignment)430 void setSourceAlignment(unsigned Alignment) { 431 setSourceAlignment(MaybeAlign(Alignment)); 432 } setSourceAlignment(MaybeAlign Alignment)433 void setSourceAlignment(MaybeAlign Alignment) { 434 BaseCL::removeParamAttr(ARG_SOURCE, Attribute::Alignment); 435 if (Alignment) 436 BaseCL::addParamAttr(ARG_SOURCE, Attribute::getWithAlignment( 437 BaseCL::getContext(), *Alignment)); 438 } setSourceAlignment(Align Alignment)439 void setSourceAlignment(Align Alignment) { 440 BaseCL::removeParamAttr(ARG_SOURCE, Attribute::Alignment); 441 BaseCL::addParamAttr(ARG_SOURCE, Attribute::getWithAlignment( 442 BaseCL::getContext(), Alignment)); 443 } 444 }; 445 446 /// Common base class for all memset intrinsics. Simply provides 447 /// common methods. 448 template <class BaseCL> class MemSetBase : public BaseCL { 449 private: 450 enum { ARG_VALUE = 1 }; 451 452 public: getValue()453 Value *getValue() const { 454 return const_cast<Value *>(BaseCL::getArgOperand(ARG_VALUE)); 455 } getValueUse()456 const Use &getValueUse() const { 457 return BaseCL::getArgOperandUse(ARG_VALUE); 458 } getValueUse()459 Use &getValueUse() { return BaseCL::getArgOperandUse(ARG_VALUE); } 460 setValue(Value * Val)461 void setValue(Value *Val) { 462 assert(getValue()->getType() == Val->getType() && 463 "setValue called with value of wrong type!"); 464 BaseCL::setArgOperand(ARG_VALUE, Val); 465 } 466 }; 467 468 // The common base class for the atomic memset/memmove/memcpy intrinsics 469 // i.e. llvm.element.unordered.atomic.memset/memcpy/memmove 470 class AtomicMemIntrinsic : public MemIntrinsicBase<AtomicMemIntrinsic> { 471 private: 472 enum { ARG_ELEMENTSIZE = 3 }; 473 474 public: getRawElementSizeInBytes()475 Value *getRawElementSizeInBytes() const { 476 return const_cast<Value *>(getArgOperand(ARG_ELEMENTSIZE)); 477 } 478 getElementSizeInBytesCst()479 ConstantInt *getElementSizeInBytesCst() const { 480 return cast<ConstantInt>(getRawElementSizeInBytes()); 481 } 482 getElementSizeInBytes()483 uint32_t getElementSizeInBytes() const { 484 return getElementSizeInBytesCst()->getZExtValue(); 485 } 486 setElementSizeInBytes(Constant * V)487 void setElementSizeInBytes(Constant *V) { 488 assert(V->getType() == Type::getInt8Ty(getContext()) && 489 "setElementSizeInBytes called with value of wrong type!"); 490 setArgOperand(ARG_ELEMENTSIZE, V); 491 } 492 classof(const IntrinsicInst * I)493 static bool classof(const IntrinsicInst *I) { 494 switch (I->getIntrinsicID()) { 495 case Intrinsic::memcpy_element_unordered_atomic: 496 case Intrinsic::memmove_element_unordered_atomic: 497 case Intrinsic::memset_element_unordered_atomic: 498 return true; 499 default: 500 return false; 501 } 502 } classof(const Value * V)503 static bool classof(const Value *V) { 504 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 505 } 506 }; 507 508 /// This class represents atomic memset intrinsic 509 // i.e. llvm.element.unordered.atomic.memset 510 class AtomicMemSetInst : public MemSetBase<AtomicMemIntrinsic> { 511 public: classof(const IntrinsicInst * I)512 static bool classof(const IntrinsicInst *I) { 513 return I->getIntrinsicID() == Intrinsic::memset_element_unordered_atomic; 514 } classof(const Value * V)515 static bool classof(const Value *V) { 516 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 517 } 518 }; 519 520 // This class wraps the atomic memcpy/memmove intrinsics 521 // i.e. llvm.element.unordered.atomic.memcpy/memmove 522 class AtomicMemTransferInst : public MemTransferBase<AtomicMemIntrinsic> { 523 public: classof(const IntrinsicInst * I)524 static bool classof(const IntrinsicInst *I) { 525 switch (I->getIntrinsicID()) { 526 case Intrinsic::memcpy_element_unordered_atomic: 527 case Intrinsic::memmove_element_unordered_atomic: 528 return true; 529 default: 530 return false; 531 } 532 } classof(const Value * V)533 static bool classof(const Value *V) { 534 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 535 } 536 }; 537 538 /// This class represents the atomic memcpy intrinsic 539 /// i.e. llvm.element.unordered.atomic.memcpy 540 class AtomicMemCpyInst : public AtomicMemTransferInst { 541 public: classof(const IntrinsicInst * I)542 static bool classof(const IntrinsicInst *I) { 543 return I->getIntrinsicID() == Intrinsic::memcpy_element_unordered_atomic; 544 } classof(const Value * V)545 static bool classof(const Value *V) { 546 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 547 } 548 }; 549 550 /// This class represents the atomic memmove intrinsic 551 /// i.e. llvm.element.unordered.atomic.memmove 552 class AtomicMemMoveInst : public AtomicMemTransferInst { 553 public: classof(const IntrinsicInst * I)554 static bool classof(const IntrinsicInst *I) { 555 return I->getIntrinsicID() == Intrinsic::memmove_element_unordered_atomic; 556 } classof(const Value * V)557 static bool classof(const Value *V) { 558 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 559 } 560 }; 561 562 /// This is the common base class for memset/memcpy/memmove. 563 class MemIntrinsic : public MemIntrinsicBase<MemIntrinsic> { 564 private: 565 enum { ARG_VOLATILE = 3 }; 566 567 public: getVolatileCst()568 ConstantInt *getVolatileCst() const { 569 return cast<ConstantInt>( 570 const_cast<Value *>(getArgOperand(ARG_VOLATILE))); 571 } 572 isVolatile()573 bool isVolatile() const { 574 return !getVolatileCst()->isZero(); 575 } 576 setVolatile(Constant * V)577 void setVolatile(Constant *V) { setArgOperand(ARG_VOLATILE, V); } 578 579 // Methods for support type inquiry through isa, cast, and dyn_cast: classof(const IntrinsicInst * I)580 static bool classof(const IntrinsicInst *I) { 581 switch (I->getIntrinsicID()) { 582 case Intrinsic::memcpy: 583 case Intrinsic::memmove: 584 case Intrinsic::memset: 585 return true; 586 default: return false; 587 } 588 } classof(const Value * V)589 static bool classof(const Value *V) { 590 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 591 } 592 }; 593 594 /// This class wraps the llvm.memset intrinsic. 595 class MemSetInst : public MemSetBase<MemIntrinsic> { 596 public: 597 // Methods for support type inquiry through isa, cast, and dyn_cast: classof(const IntrinsicInst * I)598 static bool classof(const IntrinsicInst *I) { 599 return I->getIntrinsicID() == Intrinsic::memset; 600 } classof(const Value * V)601 static bool classof(const Value *V) { 602 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 603 } 604 }; 605 606 /// This class wraps the llvm.memcpy/memmove intrinsics. 607 class MemTransferInst : public MemTransferBase<MemIntrinsic> { 608 public: 609 // Methods for support type inquiry through isa, cast, and dyn_cast: classof(const IntrinsicInst * I)610 static bool classof(const IntrinsicInst *I) { 611 return I->getIntrinsicID() == Intrinsic::memcpy || 612 I->getIntrinsicID() == Intrinsic::memmove; 613 } classof(const Value * V)614 static bool classof(const Value *V) { 615 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 616 } 617 }; 618 619 /// This class wraps the llvm.memcpy intrinsic. 620 class MemCpyInst : public MemTransferInst { 621 public: 622 // Methods for support type inquiry through isa, cast, and dyn_cast: classof(const IntrinsicInst * I)623 static bool classof(const IntrinsicInst *I) { 624 return I->getIntrinsicID() == Intrinsic::memcpy; 625 } classof(const Value * V)626 static bool classof(const Value *V) { 627 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 628 } 629 }; 630 631 /// This class wraps the llvm.memmove intrinsic. 632 class MemMoveInst : public MemTransferInst { 633 public: 634 // Methods for support type inquiry through isa, cast, and dyn_cast: classof(const IntrinsicInst * I)635 static bool classof(const IntrinsicInst *I) { 636 return I->getIntrinsicID() == Intrinsic::memmove; 637 } classof(const Value * V)638 static bool classof(const Value *V) { 639 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 640 } 641 }; 642 643 // The common base class for any memset/memmove/memcpy intrinsics; 644 // whether they be atomic or non-atomic. 645 // i.e. llvm.element.unordered.atomic.memset/memcpy/memmove 646 // and llvm.memset/memcpy/memmove 647 class AnyMemIntrinsic : public MemIntrinsicBase<AnyMemIntrinsic> { 648 public: isVolatile()649 bool isVolatile() const { 650 // Only the non-atomic intrinsics can be volatile 651 if (auto *MI = dyn_cast<MemIntrinsic>(this)) 652 return MI->isVolatile(); 653 return false; 654 } 655 classof(const IntrinsicInst * I)656 static bool classof(const IntrinsicInst *I) { 657 switch (I->getIntrinsicID()) { 658 case Intrinsic::memcpy: 659 case Intrinsic::memmove: 660 case Intrinsic::memset: 661 case Intrinsic::memcpy_element_unordered_atomic: 662 case Intrinsic::memmove_element_unordered_atomic: 663 case Intrinsic::memset_element_unordered_atomic: 664 return true; 665 default: 666 return false; 667 } 668 } classof(const Value * V)669 static bool classof(const Value *V) { 670 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 671 } 672 }; 673 674 /// This class represents any memset intrinsic 675 // i.e. llvm.element.unordered.atomic.memset 676 // and llvm.memset 677 class AnyMemSetInst : public MemSetBase<AnyMemIntrinsic> { 678 public: classof(const IntrinsicInst * I)679 static bool classof(const IntrinsicInst *I) { 680 switch (I->getIntrinsicID()) { 681 case Intrinsic::memset: 682 case Intrinsic::memset_element_unordered_atomic: 683 return true; 684 default: 685 return false; 686 } 687 } classof(const Value * V)688 static bool classof(const Value *V) { 689 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 690 } 691 }; 692 693 // This class wraps any memcpy/memmove intrinsics 694 // i.e. llvm.element.unordered.atomic.memcpy/memmove 695 // and llvm.memcpy/memmove 696 class AnyMemTransferInst : public MemTransferBase<AnyMemIntrinsic> { 697 public: classof(const IntrinsicInst * I)698 static bool classof(const IntrinsicInst *I) { 699 switch (I->getIntrinsicID()) { 700 case Intrinsic::memcpy: 701 case Intrinsic::memmove: 702 case Intrinsic::memcpy_element_unordered_atomic: 703 case Intrinsic::memmove_element_unordered_atomic: 704 return true; 705 default: 706 return false; 707 } 708 } classof(const Value * V)709 static bool classof(const Value *V) { 710 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 711 } 712 }; 713 714 /// This class represents any memcpy intrinsic 715 /// i.e. llvm.element.unordered.atomic.memcpy 716 /// and llvm.memcpy 717 class AnyMemCpyInst : public AnyMemTransferInst { 718 public: classof(const IntrinsicInst * I)719 static bool classof(const IntrinsicInst *I) { 720 switch (I->getIntrinsicID()) { 721 case Intrinsic::memcpy: 722 case Intrinsic::memcpy_element_unordered_atomic: 723 return true; 724 default: 725 return false; 726 } 727 } classof(const Value * V)728 static bool classof(const Value *V) { 729 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 730 } 731 }; 732 733 /// This class represents any memmove intrinsic 734 /// i.e. llvm.element.unordered.atomic.memmove 735 /// and llvm.memmove 736 class AnyMemMoveInst : public AnyMemTransferInst { 737 public: classof(const IntrinsicInst * I)738 static bool classof(const IntrinsicInst *I) { 739 switch (I->getIntrinsicID()) { 740 case Intrinsic::memmove: 741 case Intrinsic::memmove_element_unordered_atomic: 742 return true; 743 default: 744 return false; 745 } 746 } classof(const Value * V)747 static bool classof(const Value *V) { 748 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 749 } 750 }; 751 752 /// This represents the llvm.va_start intrinsic. 753 class VAStartInst : public IntrinsicInst { 754 public: classof(const IntrinsicInst * I)755 static bool classof(const IntrinsicInst *I) { 756 return I->getIntrinsicID() == Intrinsic::vastart; 757 } classof(const Value * V)758 static bool classof(const Value *V) { 759 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 760 } 761 getArgList()762 Value *getArgList() const { return const_cast<Value*>(getArgOperand(0)); } 763 }; 764 765 /// This represents the llvm.va_end intrinsic. 766 class VAEndInst : public IntrinsicInst { 767 public: classof(const IntrinsicInst * I)768 static bool classof(const IntrinsicInst *I) { 769 return I->getIntrinsicID() == Intrinsic::vaend; 770 } classof(const Value * V)771 static bool classof(const Value *V) { 772 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 773 } 774 getArgList()775 Value *getArgList() const { return const_cast<Value*>(getArgOperand(0)); } 776 }; 777 778 /// This represents the llvm.va_copy intrinsic. 779 class VACopyInst : public IntrinsicInst { 780 public: classof(const IntrinsicInst * I)781 static bool classof(const IntrinsicInst *I) { 782 return I->getIntrinsicID() == Intrinsic::vacopy; 783 } classof(const Value * V)784 static bool classof(const Value *V) { 785 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 786 } 787 getDest()788 Value *getDest() const { return const_cast<Value*>(getArgOperand(0)); } getSrc()789 Value *getSrc() const { return const_cast<Value*>(getArgOperand(1)); } 790 }; 791 792 /// This represents the llvm.instrprof_increment intrinsic. 793 class InstrProfIncrementInst : public IntrinsicInst { 794 public: classof(const IntrinsicInst * I)795 static bool classof(const IntrinsicInst *I) { 796 return I->getIntrinsicID() == Intrinsic::instrprof_increment; 797 } classof(const Value * V)798 static bool classof(const Value *V) { 799 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 800 } 801 getName()802 GlobalVariable *getName() const { 803 return cast<GlobalVariable>( 804 const_cast<Value *>(getArgOperand(0))->stripPointerCasts()); 805 } 806 getHash()807 ConstantInt *getHash() const { 808 return cast<ConstantInt>(const_cast<Value *>(getArgOperand(1))); 809 } 810 getNumCounters()811 ConstantInt *getNumCounters() const { 812 return cast<ConstantInt>(const_cast<Value *>(getArgOperand(2))); 813 } 814 getIndex()815 ConstantInt *getIndex() const { 816 return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3))); 817 } 818 819 Value *getStep() const; 820 }; 821 822 class InstrProfIncrementInstStep : public InstrProfIncrementInst { 823 public: classof(const IntrinsicInst * I)824 static bool classof(const IntrinsicInst *I) { 825 return I->getIntrinsicID() == Intrinsic::instrprof_increment_step; 826 } classof(const Value * V)827 static bool classof(const Value *V) { 828 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 829 } 830 }; 831 832 /// This represents the llvm.instrprof_value_profile intrinsic. 833 class InstrProfValueProfileInst : public IntrinsicInst { 834 public: classof(const IntrinsicInst * I)835 static bool classof(const IntrinsicInst *I) { 836 return I->getIntrinsicID() == Intrinsic::instrprof_value_profile; 837 } classof(const Value * V)838 static bool classof(const Value *V) { 839 return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); 840 } 841 getName()842 GlobalVariable *getName() const { 843 return cast<GlobalVariable>( 844 const_cast<Value *>(getArgOperand(0))->stripPointerCasts()); 845 } 846 getHash()847 ConstantInt *getHash() const { 848 return cast<ConstantInt>(const_cast<Value *>(getArgOperand(1))); 849 } 850 getTargetValue()851 Value *getTargetValue() const { 852 return cast<Value>(const_cast<Value *>(getArgOperand(2))); 853 } 854 getValueKind()855 ConstantInt *getValueKind() const { 856 return cast<ConstantInt>(const_cast<Value *>(getArgOperand(3))); 857 } 858 859 // Returns the value site index. getIndex()860 ConstantInt *getIndex() const { 861 return cast<ConstantInt>(const_cast<Value *>(getArgOperand(4))); 862 } 863 }; 864 865 } // end namespace llvm 866 867 #endif // LLVM_IR_INTRINSICINST_H 868