1 //===- GetElementPtrTypeIterator.h ------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements an iterator for walking through the types indexed by
11 // getelementptr instructions.
13 //===----------------------------------------------------------------------===//
15 #ifndef LLVM_IR_GETELEMENTPTRTYPEITERATOR_H
16 #define LLVM_IR_GETELEMENTPTRTYPEITERATOR_H
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"
29 template<typename ItTy = User::const_op_iterator>
30 class generic_gep_type_iterator
31 : public std::iterator<std::forward_iterator_tag, Type *, ptrdiff_t> {
32 typedef std::iterator<std::forward_iterator_tag,
33 Type *, ptrdiff_t> super;
36 PointerUnion<StructType *, Type *> CurTy;
37 enum : uint64_t { Unbounded = -1ull };
38 uint64_t NumElements = Unbounded;
39 generic_gep_type_iterator() = default;
42 static generic_gep_type_iterator begin(Type *Ty, ItTy It) {
43 generic_gep_type_iterator I;
49 static generic_gep_type_iterator end(ItTy It) {
50 generic_gep_type_iterator I;
55 bool operator==(const generic_gep_type_iterator& x) const {
56 return OpIt == x.OpIt;
59 bool operator!=(const generic_gep_type_iterator& x) const {
60 return !operator==(x);
63 // FIXME: Make this the iterator's operator*() after the 4.0 release.
64 // operator*() had a different meaning in earlier releases, so we're
65 // temporarily not giving this iterator an operator*() to avoid a subtle
67 Type *getIndexedType() const {
68 if (auto *T = CurTy.dyn_cast<Type *>())
70 return CurTy.get<StructType *>()->getTypeAtIndex(getOperand());
73 Value *getOperand() const { return const_cast<Value *>(&**OpIt); }
75 generic_gep_type_iterator& operator++() { // Preincrement
76 Type *Ty = getIndexedType();
77 if (auto *STy = dyn_cast<SequentialType>(Ty)) {
78 CurTy = STy->getElementType();
79 NumElements = STy->getNumElements();
81 CurTy = dyn_cast<StructType>(Ty);
86 generic_gep_type_iterator operator++(int) { // Postincrement
87 generic_gep_type_iterator tmp = *this; ++*this; return tmp;
90 // All of the below API is for querying properties of the "outer type", i.e.
91 // the type that contains the indexed type. Most of the time this is just
92 // the type that was visited immediately prior to the indexed type, but for
93 // the first element this is an unbounded array of the GEP's source element
94 // type, for which there is no clearly corresponding IR type (we've
95 // historically used a pointer type as the outer type in this case, but
96 // pointers will soon lose their element type).
98 // FIXME: Most current users of this class are just interested in byte
99 // offsets (a few need to know whether the outer type is a struct because
100 // they are trying to replace a constant with a variable, which is only
101 // legal for arrays, e.g. canReplaceOperandWithVariable in SimplifyCFG.cpp);
102 // we should provide a more minimal API here that exposes not much more than
105 bool isStruct() const { return CurTy.is<StructType *>(); }
106 bool isSequential() const { return CurTy.is<Type *>(); }
108 StructType *getStructType() const { return CurTy.get<StructType *>(); }
110 StructType *getStructTypeOrNull() const {
111 return CurTy.dyn_cast<StructType *>();
114 bool isBoundedSequential() const {
115 return isSequential() && NumElements != Unbounded;
118 uint64_t getSequentialNumElements() const {
119 assert(isBoundedSequential());
124 typedef generic_gep_type_iterator<> gep_type_iterator;
126 inline gep_type_iterator gep_type_begin(const User *GEP) {
127 auto *GEPOp = cast<GEPOperator>(GEP);
128 return gep_type_iterator::begin(
129 GEPOp->getSourceElementType(),
130 GEP->op_begin() + 1);
133 inline gep_type_iterator gep_type_end(const User *GEP) {
134 return gep_type_iterator::end(GEP->op_end());
137 inline gep_type_iterator gep_type_begin(const User &GEP) {
138 auto &GEPOp = cast<GEPOperator>(GEP);
139 return gep_type_iterator::begin(
140 GEPOp.getSourceElementType(),
144 inline gep_type_iterator gep_type_end(const User &GEP) {
145 return gep_type_iterator::end(GEP.op_end());
149 inline generic_gep_type_iterator<const T *>
150 gep_type_begin(Type *Op0, ArrayRef<T> A) {
151 return generic_gep_type_iterator<const T *>::begin(Op0, A.begin());
155 inline generic_gep_type_iterator<const T *>
156 gep_type_end(Type * /*Op0*/, ArrayRef<T> A) {
157 return generic_gep_type_iterator<const T *>::end(A.end());
160 } // end namespace llvm
162 #endif // LLVM_IR_GETELEMENTPTRTYPEITERATOR_H