Line data Source code
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 72179902 : generic_gep_type_iterator() = default;
42 :
43 : public:
44 : static generic_gep_type_iterator begin(Type *Ty, ItTy It) {
45 : generic_gep_type_iterator I;
46 : I.CurTy = Ty;
47 72179886 : I.OpIt = It;
48 : return I;
49 : }
50 :
51 : static generic_gep_type_iterator end(ItTy It) {
52 : generic_gep_type_iterator I;
53 16 : I.OpIt = It;
54 : return I;
55 : }
56 :
57 0 : bool operator==(const generic_gep_type_iterator& x) const {
58 0 : return OpIt == x.OpIt;
59 : }
60 :
61 : bool operator!=(const generic_gep_type_iterator& x) const {
62 101793102 : 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.
69 219177990 : Type *getIndexedType() const {
70 207270489 : if (auto *T = CurTy.dyn_cast<Type *>())
71 : return T;
72 23815002 : return CurTy.get<StructType *>()->getTypeAtIndex(getOperand());
73 : }
74 :
75 79358039 : Value *getOperand() const { return const_cast<Value *>(&**OpIt); }
76 :
77 144598983 : generic_gep_type_iterator& operator++() { // Preincrement
78 144598983 : Type *Ty = getIndexedType();
79 : if (auto *STy = dyn_cast<SequentialType>(Ty)) {
80 60872828 : CurTy = STy->getElementType();
81 60872828 : NumElements = STy->getNumElements();
82 : } else
83 : CurTy = dyn_cast<StructType>(Ty);
84 144598983 : ++OpIt;
85 144598983 : 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 :
107 : bool isStruct() const { return CurTy.is<StructType *>(); }
108 : bool isSequential() const { return CurTy.is<Type *>(); }
109 :
110 : StructType *getStructType() const { return CurTy.get<StructType *>(); }
111 :
112 : StructType *getStructTypeOrNull() const {
113 : return CurTy.dyn_cast<StructType *>();
114 : }
115 :
116 : bool isBoundedSequential() const {
117 8164 : return isSequential() && NumElements != Unbounded;
118 : }
119 :
120 0 : uint64_t getSequentialNumElements() const {
121 : assert(isBoundedSequential());
122 0 : return NumElements;
123 : }
124 : };
125 :
126 : using gep_type_iterator = generic_gep_type_iterator<>;
127 :
128 53649973 : 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 53649973 : GEP->op_begin() + 1);
133 : }
134 :
135 : inline gep_type_iterator gep_type_end(const User *GEP) {
136 : return gep_type_iterator::end(GEP->op_end());
137 : }
138 :
139 1925258 : 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 1925258 : GEP.op_begin() + 1);
144 : }
145 :
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 *>
152 0 : gep_type_begin(Type *Op0, ArrayRef<T> A) {
153 0 : 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 *>
158 0 : gep_type_end(Type * /*Op0*/, ArrayRef<T> A) {
159 0 : return generic_gep_type_iterator<const T *>::end(A.end());
160 : }
161 :
162 : } // end namespace llvm
163 :
164 : #endif // LLVM_IR_GETELEMENTPTRTYPEITERATOR_H
|