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 }; 243 244 /// Utility class for floating point operations which can have 245 /// information about relaxed accuracy requirements attached to them. 246 class FPMathOperator : public Operator { 247 private: 248 friend class Instruction; 249 250 /// 'Fast' means all bits are set. setFast(bool B)251 void setFast(bool B) { 252 setHasAllowReassoc(B); 253 setHasNoNaNs(B); 254 setHasNoInfs(B); 255 setHasNoSignedZeros(B); 256 setHasAllowReciprocal(B); 257 setHasAllowContract(B); 258 setHasApproxFunc(B); 259 } 260 setHasAllowReassoc(bool B)261 void setHasAllowReassoc(bool B) { 262 SubclassOptionalData = 263 (SubclassOptionalData & ~FastMathFlags::AllowReassoc) | 264 (B * FastMathFlags::AllowReassoc); 265 } 266 setHasNoNaNs(bool B)267 void setHasNoNaNs(bool B) { 268 SubclassOptionalData = 269 (SubclassOptionalData & ~FastMathFlags::NoNaNs) | 270 (B * FastMathFlags::NoNaNs); 271 } 272 setHasNoInfs(bool B)273 void setHasNoInfs(bool B) { 274 SubclassOptionalData = 275 (SubclassOptionalData & ~FastMathFlags::NoInfs) | 276 (B * FastMathFlags::NoInfs); 277 } 278 setHasNoSignedZeros(bool B)279 void setHasNoSignedZeros(bool B) { 280 SubclassOptionalData = 281 (SubclassOptionalData & ~FastMathFlags::NoSignedZeros) | 282 (B * FastMathFlags::NoSignedZeros); 283 } 284 setHasAllowReciprocal(bool B)285 void setHasAllowReciprocal(bool B) { 286 SubclassOptionalData = 287 (SubclassOptionalData & ~FastMathFlags::AllowReciprocal) | 288 (B * FastMathFlags::AllowReciprocal); 289 } 290 setHasAllowContract(bool B)291 void setHasAllowContract(bool B) { 292 SubclassOptionalData = 293 (SubclassOptionalData & ~FastMathFlags::AllowContract) | 294 (B * FastMathFlags::AllowContract); 295 } 296 setHasApproxFunc(bool B)297 void setHasApproxFunc(bool B) { 298 SubclassOptionalData = 299 (SubclassOptionalData & ~FastMathFlags::ApproxFunc) | 300 (B * FastMathFlags::ApproxFunc); 301 } 302 303 /// Convenience function for setting multiple fast-math flags. 304 /// FMF is a mask of the bits to set. setFastMathFlags(FastMathFlags FMF)305 void setFastMathFlags(FastMathFlags FMF) { 306 SubclassOptionalData |= FMF.Flags; 307 } 308 309 /// Convenience function for copying all fast-math flags. 310 /// All values in FMF are transferred to this operator. copyFastMathFlags(FastMathFlags FMF)311 void copyFastMathFlags(FastMathFlags FMF) { 312 SubclassOptionalData = FMF.Flags; 313 } 314 315 public: 316 /// Test if this operation allows all non-strict floating-point transforms. isFast()317 bool isFast() const { 318 return ((SubclassOptionalData & FastMathFlags::AllowReassoc) != 0 && 319 (SubclassOptionalData & FastMathFlags::NoNaNs) != 0 && 320 (SubclassOptionalData & FastMathFlags::NoInfs) != 0 && 321 (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0 && 322 (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0 && 323 (SubclassOptionalData & FastMathFlags::AllowContract) != 0 && 324 (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0); 325 } 326 327 /// Test if this operation may be simplified with reassociative transforms. hasAllowReassoc()328 bool hasAllowReassoc() const { 329 return (SubclassOptionalData & FastMathFlags::AllowReassoc) != 0; 330 } 331 332 /// Test if this operation's arguments and results are assumed not-NaN. hasNoNaNs()333 bool hasNoNaNs() const { 334 return (SubclassOptionalData & FastMathFlags::NoNaNs) != 0; 335 } 336 337 /// Test if this operation's arguments and results are assumed not-infinite. hasNoInfs()338 bool hasNoInfs() const { 339 return (SubclassOptionalData & FastMathFlags::NoInfs) != 0; 340 } 341 342 /// Test if this operation can ignore the sign of zero. hasNoSignedZeros()343 bool hasNoSignedZeros() const { 344 return (SubclassOptionalData & FastMathFlags::NoSignedZeros) != 0; 345 } 346 347 /// Test if this operation can use reciprocal multiply instead of division. hasAllowReciprocal()348 bool hasAllowReciprocal() const { 349 return (SubclassOptionalData & FastMathFlags::AllowReciprocal) != 0; 350 } 351 352 /// Test if this operation can be floating-point contracted (FMA). hasAllowContract()353 bool hasAllowContract() const { 354 return (SubclassOptionalData & FastMathFlags::AllowContract) != 0; 355 } 356 357 /// Test if this operation allows approximations of math library functions or 358 /// intrinsics. hasApproxFunc()359 bool hasApproxFunc() const { 360 return (SubclassOptionalData & FastMathFlags::ApproxFunc) != 0; 361 } 362 363 /// Convenience function for getting all the fast-math flags getFastMathFlags()364 FastMathFlags getFastMathFlags() const { 365 return FastMathFlags(SubclassOptionalData); 366 } 367 368 /// Get the maximum error permitted by this operation in ULPs. An accuracy of 369 /// 0.0 means that the operation should be performed with the default 370 /// precision. 371 float getFPAccuracy() const; 372 classof(const Value * V)373 static bool classof(const Value *V) { 374 unsigned Opcode; 375 if (auto *I = dyn_cast<Instruction>(V)) 376 Opcode = I->getOpcode(); 377 else if (auto *CE = dyn_cast<ConstantExpr>(V)) 378 Opcode = CE->getOpcode(); 379 else 380 return false; 381 382 switch (Opcode) { 383 case Instruction::FNeg: 384 case Instruction::FAdd: 385 case Instruction::FSub: 386 case Instruction::FMul: 387 case Instruction::FDiv: 388 case Instruction::FRem: 389 // FIXME: To clean up and correct the semantics of fast-math-flags, FCmp 390 // should not be treated as a math op, but the other opcodes should. 391 // This would make things consistent with Select/PHI (FP value type 392 // determines whether they are math ops and, therefore, capable of 393 // having fast-math-flags). 394 case Instruction::FCmp: 395 return true; 396 case Instruction::PHI: 397 case Instruction::Select: 398 case Instruction::Call: { 399 Type *Ty = V->getType(); 400 while (ArrayType *ArrTy = dyn_cast<ArrayType>(Ty)) 401 Ty = ArrTy->getElementType(); 402 return Ty->isFPOrFPVectorTy(); 403 } 404 default: 405 return false; 406 } 407 } 408 }; 409 410 /// A helper template for defining operators for individual opcodes. 411 template<typename SuperClass, unsigned Opc> 412 class ConcreteOperator : public SuperClass { 413 public: classof(const Instruction * I)414 static bool classof(const Instruction *I) { 415 return I->getOpcode() == Opc; 416 } classof(const ConstantExpr * CE)417 static bool classof(const ConstantExpr *CE) { 418 return CE->getOpcode() == Opc; 419 } classof(const Value * V)420 static bool classof(const Value *V) { 421 return (isa<Instruction>(V) && classof(cast<Instruction>(V))) || 422 (isa<ConstantExpr>(V) && classof(cast<ConstantExpr>(V))); 423 } 424 }; 425 426 class AddOperator 427 : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Add> { 428 }; 429 class SubOperator 430 : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Sub> { 431 }; 432 class MulOperator 433 : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Mul> { 434 }; 435 class ShlOperator 436 : public ConcreteOperator<OverflowingBinaryOperator, Instruction::Shl> { 437 }; 438 439 class SDivOperator 440 : public ConcreteOperator<PossiblyExactOperator, Instruction::SDiv> { 441 }; 442 class UDivOperator 443 : public ConcreteOperator<PossiblyExactOperator, Instruction::UDiv> { 444 }; 445 class AShrOperator 446 : public ConcreteOperator<PossiblyExactOperator, Instruction::AShr> { 447 }; 448 class LShrOperator 449 : public ConcreteOperator<PossiblyExactOperator, Instruction::LShr> { 450 }; 451 452 class ZExtOperator : public ConcreteOperator<Operator, Instruction::ZExt> {}; 453 454 class GEPOperator 455 : public ConcreteOperator<Operator, Instruction::GetElementPtr> { 456 friend class GetElementPtrInst; 457 friend class ConstantExpr; 458 459 enum { 460 IsInBounds = (1 << 0), 461 // InRangeIndex: bits 1-6 462 }; 463 setIsInBounds(bool B)464 void setIsInBounds(bool B) { 465 SubclassOptionalData = 466 (SubclassOptionalData & ~IsInBounds) | (B * IsInBounds); 467 } 468 469 public: 470 /// Test whether this is an inbounds GEP, as defined by LangRef.html. isInBounds()471 bool isInBounds() const { 472 return SubclassOptionalData & IsInBounds; 473 } 474 475 /// Returns the offset of the index with an inrange attachment, or None if 476 /// none. getInRangeIndex()477 Optional<unsigned> getInRangeIndex() const { 478 if (SubclassOptionalData >> 1 == 0) return None; 479 return (SubclassOptionalData >> 1) - 1; 480 } 481 idx_begin()482 inline op_iterator idx_begin() { return op_begin()+1; } idx_begin()483 inline const_op_iterator idx_begin() const { return op_begin()+1; } idx_end()484 inline op_iterator idx_end() { return op_end(); } idx_end()485 inline const_op_iterator idx_end() const { return op_end(); } 486 getPointerOperand()487 Value *getPointerOperand() { 488 return getOperand(0); 489 } getPointerOperand()490 const Value *getPointerOperand() const { 491 return getOperand(0); 492 } getPointerOperandIndex()493 static unsigned getPointerOperandIndex() { 494 return 0U; // get index for modifying correct operand 495 } 496 497 /// Method to return the pointer operand as a PointerType. getPointerOperandType()498 Type *getPointerOperandType() const { 499 return getPointerOperand()->getType(); 500 } 501 502 Type *getSourceElementType() const; 503 Type *getResultElementType() const; 504 505 /// Method to return the address space of the pointer operand. getPointerAddressSpace()506 unsigned getPointerAddressSpace() const { 507 return getPointerOperandType()->getPointerAddressSpace(); 508 } 509 getNumIndices()510 unsigned getNumIndices() const { // Note: always non-negative 511 return getNumOperands() - 1; 512 } 513 hasIndices()514 bool hasIndices() const { 515 return getNumOperands() > 1; 516 } 517 518 /// Return true if all of the indices of this GEP are zeros. 519 /// If so, the result pointer and the first operand have the same 520 /// value, just potentially different types. hasAllZeroIndices()521 bool hasAllZeroIndices() const { 522 for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { 523 if (ConstantInt *C = dyn_cast<ConstantInt>(I)) 524 if (C->isZero()) 525 continue; 526 return false; 527 } 528 return true; 529 } 530 531 /// Return true if all of the indices of this GEP are constant integers. 532 /// If so, the result pointer and the first operand have 533 /// a constant offset between them. hasAllConstantIndices()534 bool hasAllConstantIndices() const { 535 for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { 536 if (!isa<ConstantInt>(I)) 537 return false; 538 } 539 return true; 540 } 541 countNonConstantIndices()542 unsigned countNonConstantIndices() const { 543 return count_if(make_range(idx_begin(), idx_end()), [](const Use& use) { 544 return !isa<ConstantInt>(*use); 545 }); 546 } 547 548 /// Compute the maximum alignment that this GEP is garranteed to preserve. 549 Align getMaxPreservedAlignment(const DataLayout &DL) const; 550 551 /// Accumulate the constant address offset of this GEP if possible. 552 /// 553 /// This routine accepts an APInt into which it will try to accumulate the 554 /// constant offset of this GEP. 555 /// 556 /// If \p ExternalAnalysis is provided it will be used to calculate a offset 557 /// when a operand of GEP is not constant. 558 /// For example, for a value \p ExternalAnalysis might try to calculate a 559 /// lower bound. If \p ExternalAnalysis is successful, it should return true. 560 /// 561 /// If the \p ExternalAnalysis returns false or the value returned by \p 562 /// ExternalAnalysis results in a overflow/underflow, this routine returns 563 /// false and the value of the offset APInt is undefined (it is *not* 564 /// preserved!). 565 /// 566 /// The APInt passed into this routine must be at exactly as wide as the 567 /// IntPtr type for the address space of the base GEP pointer. 568 bool accumulateConstantOffset( 569 const DataLayout &DL, APInt &Offset, 570 function_ref<bool(Value &, APInt &)> ExternalAnalysis = nullptr) const; 571 }; 572 573 class PtrToIntOperator 574 : public ConcreteOperator<Operator, Instruction::PtrToInt> { 575 friend class PtrToInt; 576 friend class ConstantExpr; 577 578 public: getPointerOperand()579 Value *getPointerOperand() { 580 return getOperand(0); 581 } getPointerOperand()582 const Value *getPointerOperand() const { 583 return getOperand(0); 584 } 585 getPointerOperandIndex()586 static unsigned getPointerOperandIndex() { 587 return 0U; // get index for modifying correct operand 588 } 589 590 /// Method to return the pointer operand as a PointerType. getPointerOperandType()591 Type *getPointerOperandType() const { 592 return getPointerOperand()->getType(); 593 } 594 595 /// Method to return the address space of the pointer operand. getPointerAddressSpace()596 unsigned getPointerAddressSpace() const { 597 return cast<PointerType>(getPointerOperandType())->getAddressSpace(); 598 } 599 }; 600 601 class BitCastOperator 602 : public ConcreteOperator<Operator, Instruction::BitCast> { 603 friend class BitCastInst; 604 friend class ConstantExpr; 605 606 public: getSrcTy()607 Type *getSrcTy() const { 608 return getOperand(0)->getType(); 609 } 610 getDestTy()611 Type *getDestTy() const { 612 return getType(); 613 } 614 }; 615 616 class AddrSpaceCastOperator 617 : public ConcreteOperator<Operator, Instruction::AddrSpaceCast> { 618 friend class AddrSpaceCastInst; 619 friend class ConstantExpr; 620 621 public: getPointerOperand()622 Value *getPointerOperand() { return getOperand(0); } 623 getPointerOperand()624 const Value *getPointerOperand() const { return getOperand(0); } 625 getSrcAddressSpace()626 unsigned getSrcAddressSpace() const { 627 return getPointerOperand()->getType()->getPointerAddressSpace(); 628 } 629 getDestAddressSpace()630 unsigned getDestAddressSpace() const { 631 return getType()->getPointerAddressSpace(); 632 } 633 }; 634 635 } // end namespace llvm 636 637 #endif // LLVM_IR_OPERATOR_H 638