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, ItTy It) { 37 generic_gep_type_iterator I; 38 I.CurTy.setPointer(Ty); 39 I.OpIt = It; 40 return I; 41 } 42 static generic_gep_type_iterator begin(Type *Ty, unsigned AddrSpace, 43 ItTy It) { 44 generic_gep_type_iterator I; 45 I.CurTy.setPointer(Ty); 46 I.CurTy.setInt(true); 47 I.AddrSpace = AddrSpace; 48 I.OpIt = It; 49 return I; 50 } 51 static generic_gep_type_iterator end(ItTy It) { 52 generic_gep_type_iterator I; 53 I.OpIt = It; 54 return I; 55 } 56 57 bool operator==(const generic_gep_type_iterator& x) const { 58 return OpIt == x.OpIt; 59 } 60 bool operator!=(const generic_gep_type_iterator& x) const { 61 return !operator==(x); 62 } 63 64 Type *operator*() const { 65 if (CurTy.getInt()) 66 return CurTy.getPointer()->getPointerTo(AddrSpace); 67 return CurTy.getPointer(); 68 } 69 70 Type *getIndexedType() const { 71 if (CurTy.getInt()) 72 return CurTy.getPointer(); 73 CompositeType *CT = cast<CompositeType>(CurTy.getPointer()); 74 return CT->getTypeAtIndex(getOperand()); 75 } 76 77 // This is a non-standard operator->. It allows you to call methods on the 78 // current type directly. 79 Type *operator->() const { return operator*(); } 80 81 Value *getOperand() const { return const_cast<Value *>(&**OpIt); } 82 83 generic_gep_type_iterator& operator++() { // Preincrement 84 if (CurTy.getInt()) { 85 CurTy.setInt(false); 86 } else if (CompositeType *CT = 87 dyn_cast<CompositeType>(CurTy.getPointer())) { 88 CurTy.setPointer(CT->getTypeAtIndex(getOperand())); 89 } else { 90 CurTy.setPointer(nullptr); 91 } 92 ++OpIt; 93 return *this; 94 } 95 96 generic_gep_type_iterator operator++(int) { // Postincrement 97 generic_gep_type_iterator tmp = *this; ++*this; return tmp; 98 } 99 }; 100 101 typedef generic_gep_type_iterator<> gep_type_iterator; 102 103 inline gep_type_iterator gep_type_begin(const User *GEP) { 104 auto *GEPOp = cast<GEPOperator>(GEP); 105 return gep_type_iterator::begin( 106 GEPOp->getSourceElementType(), 107 cast<PointerType>(GEPOp->getPointerOperandType()->getScalarType()) 108 ->getAddressSpace(), 109 GEP->op_begin() + 1); 110 } 111 inline gep_type_iterator gep_type_end(const User *GEP) { 112 return gep_type_iterator::end(GEP->op_end()); 113 } 114 inline gep_type_iterator gep_type_begin(const User &GEP) { 115 auto &GEPOp = cast<GEPOperator>(GEP); 116 return gep_type_iterator::begin( 117 GEPOp.getSourceElementType(), 118 cast<PointerType>(GEPOp.getPointerOperandType()->getScalarType()) 119 ->getAddressSpace(), 120 GEP.op_begin() + 1); 121 } 122 inline gep_type_iterator gep_type_end(const User &GEP) { 123 return gep_type_iterator::end(GEP.op_end()); 124 } 125 126 template<typename T> 127 inline generic_gep_type_iterator<const T *> 128 gep_type_begin(Type *Op0, ArrayRef<T> A) { 129 return generic_gep_type_iterator<const T *>::begin(Op0, A.begin()); 130 } 131 132 template<typename T> 133 inline generic_gep_type_iterator<const T *> 134 gep_type_end(Type * /*Op0*/, ArrayRef<T> A) { 135 return generic_gep_type_iterator<const T *>::end(A.end()); 136 } 137 } // end namespace llvm 138 139 #endif 140