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/ADT/ArrayRef.h" 19 #include "llvm/ADT/PointerUnion.h" 20 #include "llvm/IR/DerivedTypes.h" 21 #include "llvm/IR/Operator.h" 22 #include "llvm/IR/User.h" 23 #include "llvm/Support/Casting.h" 24 #include <cassert> 25 #include <cstddef> 26 #include <cstdint> 27 #include <iterator> 28 29 namespace llvm { 30 31 template<typename ItTy = User::const_op_iterator> 32 class generic_gep_type_iterator 33 : public std::iterator<std::forward_iterator_tag, Type *, ptrdiff_t> { 34 using super = std::iterator<std::forward_iterator_tag, Type *, ptrdiff_t>; 35 36 ItTy OpIt; 37 PointerUnion<StructType *, Type *> CurTy; 38 enum : uint64_t { Unbounded = -1ull }; 39 uint64_t NumElements = Unbounded; 40 41 generic_gep_type_iterator() = default; 42 43 public: begin(Type * Ty,ItTy It)44 static generic_gep_type_iterator begin(Type *Ty, ItTy It) { 45 generic_gep_type_iterator I; 46 I.CurTy = Ty; 47 I.OpIt = It; 48 return I; 49 } 50 end(ItTy It)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 61 bool operator!=(const generic_gep_type_iterator& x) const { 62 return !operator==(x); 63 } 64 65 // FIXME: Make this the iterator's operator*() after the 4.0 release. 66 // operator*() had a different meaning in earlier releases, so we're 67 // temporarily not giving this iterator an operator*() to avoid a subtle 68 // semantics break. getIndexedType()69 Type *getIndexedType() const { 70 if (auto *T = CurTy.dyn_cast<Type *>()) 71 return T; 72 return CurTy.get<StructType *>()->getTypeAtIndex(getOperand()); 73 } 74 getOperand()75 Value *getOperand() const { return const_cast<Value *>(&**OpIt); } 76 77 generic_gep_type_iterator& operator++() { // Preincrement 78 Type *Ty = getIndexedType(); 79 if (auto *STy = dyn_cast<SequentialType>(Ty)) { 80 CurTy = STy->getElementType(); 81 NumElements = STy->getNumElements(); 82 } else 83 CurTy = dyn_cast<StructType>(Ty); 84 ++OpIt; 85 return *this; 86 } 87 88 generic_gep_type_iterator operator++(int) { // Postincrement 89 generic_gep_type_iterator tmp = *this; ++*this; return tmp; 90 } 91 92 // All of the below API is for querying properties of the "outer type", i.e. 93 // the type that contains the indexed type. Most of the time this is just 94 // the type that was visited immediately prior to the indexed type, but for 95 // the first element this is an unbounded array of the GEP's source element 96 // type, for which there is no clearly corresponding IR type (we've 97 // historically used a pointer type as the outer type in this case, but 98 // pointers will soon lose their element type). 99 // 100 // FIXME: Most current users of this class are just interested in byte 101 // offsets (a few need to know whether the outer type is a struct because 102 // they are trying to replace a constant with a variable, which is only 103 // legal for arrays, e.g. canReplaceOperandWithVariable in SimplifyCFG.cpp); 104 // we should provide a more minimal API here that exposes not much more than 105 // that. 106 isStruct()107 bool isStruct() const { return CurTy.is<StructType *>(); } isSequential()108 bool isSequential() const { return CurTy.is<Type *>(); } 109 getStructType()110 StructType *getStructType() const { return CurTy.get<StructType *>(); } 111 getStructTypeOrNull()112 StructType *getStructTypeOrNull() const { 113 return CurTy.dyn_cast<StructType *>(); 114 } 115 isBoundedSequential()116 bool isBoundedSequential() const { 117 return isSequential() && NumElements != Unbounded; 118 } 119 getSequentialNumElements()120 uint64_t getSequentialNumElements() const { 121 assert(isBoundedSequential()); 122 return NumElements; 123 } 124 }; 125 126 using gep_type_iterator = generic_gep_type_iterator<>; 127 gep_type_begin(const User * GEP)128 inline gep_type_iterator gep_type_begin(const User *GEP) { 129 auto *GEPOp = cast<GEPOperator>(GEP); 130 return gep_type_iterator::begin( 131 GEPOp->getSourceElementType(), 132 GEP->op_begin() + 1); 133 } 134 gep_type_end(const User * GEP)135 inline gep_type_iterator gep_type_end(const User *GEP) { 136 return gep_type_iterator::end(GEP->op_end()); 137 } 138 gep_type_begin(const User & GEP)139 inline gep_type_iterator gep_type_begin(const User &GEP) { 140 auto &GEPOp = cast<GEPOperator>(GEP); 141 return gep_type_iterator::begin( 142 GEPOp.getSourceElementType(), 143 GEP.op_begin() + 1); 144 } 145 gep_type_end(const User & GEP)146 inline gep_type_iterator gep_type_end(const User &GEP) { 147 return gep_type_iterator::end(GEP.op_end()); 148 } 149 150 template<typename T> 151 inline generic_gep_type_iterator<const T *> gep_type_begin(Type * Op0,ArrayRef<T> A)152 gep_type_begin(Type *Op0, ArrayRef<T> A) { 153 return generic_gep_type_iterator<const T *>::begin(Op0, A.begin()); 154 } 155 156 template<typename T> 157 inline generic_gep_type_iterator<const T *> gep_type_end(Type *,ArrayRef<T> A)158 gep_type_end(Type * /*Op0*/, ArrayRef<T> A) { 159 return generic_gep_type_iterator<const T *>::end(A.end()); 160 } 161 162 } // end namespace llvm 163 164 #endif // LLVM_IR_GETELEMENTPTRTYPEITERATOR_H 165