1 //===- GetElementPtrTypeIterator.h ------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements an iterator for walking through the types indexed by 11 // getelementptr instructions. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_IR_GETELEMENTPTRTYPEITERATOR_H 16 #define LLVM_IR_GETELEMENTPTRTYPEITERATOR_H 17 18 #include "llvm/IR/DerivedTypes.h" 19 #include "llvm/IR/Operator.h" 20 #include "llvm/IR/User.h" 21 #include "llvm/ADT/PointerIntPair.h" 22 23 namespace llvm { 24 template<typename ItTy = User::const_op_iterator> 25 class generic_gep_type_iterator 26 : public std::iterator<std::forward_iterator_tag, Type *, ptrdiff_t> { 27 typedef std::iterator<std::forward_iterator_tag, 28 Type *, ptrdiff_t> super; 29 30 ItTy OpIt; 31 PointerIntPair<Type *, 1> CurTy; 32 unsigned AddrSpace; 33 generic_gep_type_iterator() {} 34 public: 35 36 static generic_gep_type_iterator begin(Type *Ty, unsigned AddrSpace, 37 ItTy It) { 38 generic_gep_type_iterator I; 39 I.CurTy.setPointer(Ty); 40 I.CurTy.setInt(true); 41 I.AddrSpace = AddrSpace; 42 I.OpIt = It; 43 return I; 44 } 45 static generic_gep_type_iterator end(ItTy It) { 46 generic_gep_type_iterator I; 47 I.OpIt = It; 48 return I; 49 } 50 51 bool operator==(const generic_gep_type_iterator& x) const { 52 return OpIt == x.OpIt; 53 } 54 bool operator!=(const generic_gep_type_iterator& x) const { 55 return !operator==(x); 56 } 57 58 Type *operator*() const { 59 if (CurTy.getInt()) 60 return CurTy.getPointer()->getPointerTo(AddrSpace); 61 return CurTy.getPointer(); 62 } 63 64 Type *getIndexedType() const { 65 if (CurTy.getInt()) 66 return CurTy.getPointer(); 67 CompositeType *CT = cast<CompositeType>(CurTy.getPointer()); 68 return CT->getTypeAtIndex(getOperand()); 69 } 70 71 // This is a non-standard operator->. It allows you to call methods on the 72 // current type directly. 73 Type *operator->() const { return operator*(); } 74 75 Value *getOperand() const { return const_cast<Value *>(&**OpIt); } 76 77 generic_gep_type_iterator& operator++() { // Preincrement 78 if (CurTy.getInt()) { 79 CurTy.setInt(false); 80 } else if (CompositeType *CT = 81 dyn_cast<CompositeType>(CurTy.getPointer())) { 82 CurTy.setPointer(CT->getTypeAtIndex(getOperand())); 83 } else { 84 CurTy.setPointer(nullptr); 85 } 86 ++OpIt; 87 return *this; 88 } 89 90 generic_gep_type_iterator operator++(int) { // Postincrement 91 generic_gep_type_iterator tmp = *this; ++*this; return tmp; 92 } 93 }; 94 95 typedef generic_gep_type_iterator<> gep_type_iterator; 96 97 inline gep_type_iterator gep_type_begin(const User *GEP) { 98 auto *GEPOp = cast<GEPOperator>(GEP); 99 return gep_type_iterator::begin( 100 GEPOp->getSourceElementType(), 101 cast<PointerType>(GEPOp->getPointerOperandType()->getScalarType()) 102 ->getAddressSpace(), 103 GEP->op_begin() + 1); 104 } 105 inline gep_type_iterator gep_type_end(const User *GEP) { 106 return gep_type_iterator::end(GEP->op_end()); 107 } 108 inline gep_type_iterator gep_type_begin(const User &GEP) { 109 auto &GEPOp = cast<GEPOperator>(GEP); 110 return gep_type_iterator::begin( 111 GEPOp.getSourceElementType(), 112 cast<PointerType>(GEPOp.getPointerOperandType()->getScalarType()) 113 ->getAddressSpace(), 114 GEP.op_begin() + 1); 115 } 116 inline gep_type_iterator gep_type_end(const User &GEP) { 117 return gep_type_iterator::end(GEP.op_end()); 118 } 119 120 template<typename T> 121 inline generic_gep_type_iterator<const T *> 122 gep_type_begin(Type *Op0, unsigned AS, ArrayRef<T> A) { 123 return generic_gep_type_iterator<const T *>::begin(Op0, AS, A.begin()); 124 } 125 126 template<typename T> 127 inline generic_gep_type_iterator<const T *> 128 gep_type_end(Type * /*Op0*/, unsigned /*AS*/, ArrayRef<T> A) { 129 return generic_gep_type_iterator<const T *>::end(A.end()); 130 } 131 } // end namespace llvm 132 133 #endif 134