]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/IR/GetElementPtrTypeIterator.h
Merge ^/head r311940 through r312200.
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / IR / GetElementPtrTypeIterator.h
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 <cstddef>
25 #include <iterator>
26
27 namespace llvm {
28
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;
34
35     ItTy OpIt;
36     PointerUnion<StructType *, Type *> CurTy;
37     enum : uint64_t { Unbounded = -1ull };
38     uint64_t NumElements = Unbounded;
39     generic_gep_type_iterator() = default;
40
41   public:
42     static generic_gep_type_iterator begin(Type *Ty, ItTy It) {
43       generic_gep_type_iterator I;
44       I.CurTy = Ty;
45       I.OpIt = It;
46       return I;
47     }
48
49     static generic_gep_type_iterator end(ItTy It) {
50       generic_gep_type_iterator I;
51       I.OpIt = It;
52       return I;
53     }
54
55     bool operator==(const generic_gep_type_iterator& x) const {
56       return OpIt == x.OpIt;
57     }
58
59     bool operator!=(const generic_gep_type_iterator& x) const {
60       return !operator==(x);
61     }
62
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
66     // semantics break.
67     Type *getIndexedType() const {
68       if (auto *T = CurTy.dyn_cast<Type *>())
69         return T;
70       return CurTy.get<StructType *>()->getTypeAtIndex(getOperand());
71     }
72
73     Value *getOperand() const { return const_cast<Value *>(&**OpIt); }
74
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();
80       } else
81         CurTy = dyn_cast<StructType>(Ty);
82       ++OpIt;
83       return *this;
84     }
85
86     generic_gep_type_iterator operator++(int) { // Postincrement
87       generic_gep_type_iterator tmp = *this; ++*this; return tmp;
88     }
89
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).
97     //
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
103     // that.
104
105     bool isStruct() const { return CurTy.is<StructType *>(); }
106     bool isSequential() const { return CurTy.is<Type *>(); }
107
108     StructType *getStructType() const { return CurTy.get<StructType *>(); }
109
110     StructType *getStructTypeOrNull() const {
111       return CurTy.dyn_cast<StructType *>();
112     }
113
114     bool isBoundedSequential() const {
115       return isSequential() && NumElements != Unbounded;
116     }
117
118     uint64_t getSequentialNumElements() const {
119       assert(isBoundedSequential());
120       return NumElements;
121     }
122   };
123
124   typedef generic_gep_type_iterator<> gep_type_iterator;
125
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);
131   }
132
133   inline gep_type_iterator gep_type_end(const User *GEP) {
134     return gep_type_iterator::end(GEP->op_end());
135   }
136
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(),
141         GEP.op_begin() + 1);
142   }
143
144   inline gep_type_iterator gep_type_end(const User &GEP) {
145     return gep_type_iterator::end(GEP.op_end());
146   }
147
148   template<typename T>
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());
152   }
153
154   template<typename T>
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());
158   }
159
160 } // end namespace llvm
161
162 #endif // LLVM_IR_GETELEMENTPTRTYPEITERATOR_H