/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/include/llvm/IR/GetElementPtrTypeIterator.h
Line | Count | Source |
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 | 317M | generic_gep_type_iterator() = default; llvm::generic_gep_type_iterator<llvm::Use const*>::generic_gep_type_iterator() Line | Count | Source | 41 | 268M | generic_gep_type_iterator() = default; |
llvm::generic_gep_type_iterator<llvm::Value const* const*>::generic_gep_type_iterator() Line | Count | Source | 41 | 6.17M | generic_gep_type_iterator() = default; |
llvm::generic_gep_type_iterator<llvm::Value* const*>::generic_gep_type_iterator() Line | Count | Source | 41 | 42.5M | generic_gep_type_iterator() = default; |
|
42 | | |
43 | | public: |
44 | 264M | static generic_gep_type_iterator begin(Type *Ty, ItTy It) { |
45 | 264M | generic_gep_type_iterator I; |
46 | 264M | I.CurTy = Ty; |
47 | 264M | I.OpIt = It; |
48 | 264M | return I; |
49 | 264M | } llvm::generic_gep_type_iterator<llvm::Value* const*>::begin(llvm::Type*, llvm::Value* const*) Line | Count | Source | 44 | 21.2M | static generic_gep_type_iterator begin(Type *Ty, ItTy It) { | 45 | 21.2M | generic_gep_type_iterator I; | 46 | 21.2M | I.CurTy = Ty; | 47 | 21.2M | I.OpIt = It; | 48 | 21.2M | return I; | 49 | 21.2M | } |
llvm::generic_gep_type_iterator<llvm::Value const* const*>::begin(llvm::Type*, llvm::Value const* const*) Line | Count | Source | 44 | 6.17M | static generic_gep_type_iterator begin(Type *Ty, ItTy It) { | 45 | 6.17M | generic_gep_type_iterator I; | 46 | 6.17M | I.CurTy = Ty; | 47 | 6.17M | I.OpIt = It; | 48 | 6.17M | return I; | 49 | 6.17M | } |
llvm::generic_gep_type_iterator<llvm::Use const*>::begin(llvm::Type*, llvm::Use const*) Line | Count | Source | 44 | 236M | static generic_gep_type_iterator begin(Type *Ty, ItTy It) { | 45 | 236M | generic_gep_type_iterator I; | 46 | 236M | I.CurTy = Ty; | 47 | 236M | I.OpIt = It; | 48 | 236M | return I; | 49 | 236M | } |
|
50 | | |
51 | 52.8M | static generic_gep_type_iterator end(ItTy It) { |
52 | 52.8M | generic_gep_type_iterator I; |
53 | 52.8M | I.OpIt = It; |
54 | 52.8M | return I; |
55 | 52.8M | } llvm::generic_gep_type_iterator<llvm::Value* const*>::end(llvm::Value* const*) Line | Count | Source | 51 | 21.2M | static generic_gep_type_iterator end(ItTy It) { | 52 | 21.2M | generic_gep_type_iterator I; | 53 | 21.2M | I.OpIt = It; | 54 | 21.2M | return I; | 55 | 21.2M | } |
llvm::generic_gep_type_iterator<llvm::Use const*>::end(llvm::Use const*) Line | Count | Source | 51 | 31.6M | static generic_gep_type_iterator end(ItTy It) { | 52 | 31.6M | generic_gep_type_iterator I; | 53 | 31.6M | I.OpIt = It; | 54 | 31.6M | return I; | 55 | 31.6M | } |
|
56 | | |
57 | 164M | bool operator==(const generic_gep_type_iterator& x) const { |
58 | 164M | return OpIt == x.OpIt; |
59 | 164M | } llvm::generic_gep_type_iterator<llvm::Value* const*>::operator==(llvm::generic_gep_type_iterator<llvm::Value* const*> const&) const Line | Count | Source | 57 | 64.7M | bool operator==(const generic_gep_type_iterator& x) const { | 58 | 64.7M | return OpIt == x.OpIt; | 59 | 64.7M | } |
llvm::generic_gep_type_iterator<llvm::Use const*>::operator==(llvm::generic_gep_type_iterator<llvm::Use const*> const&) const Line | Count | Source | 57 | 99.3M | bool operator==(const generic_gep_type_iterator& x) const { | 58 | 99.3M | return OpIt == x.OpIt; | 59 | 99.3M | } |
|
60 | | |
61 | 164M | bool operator!=(const generic_gep_type_iterator& x) const { |
62 | 164M | return !operator==(x); |
63 | 164M | } llvm::generic_gep_type_iterator<llvm::Value* const*>::operator!=(llvm::generic_gep_type_iterator<llvm::Value* const*> const&) const Line | Count | Source | 61 | 64.7M | bool operator!=(const generic_gep_type_iterator& x) const { | 62 | 64.7M | return !operator==(x); | 63 | 64.7M | } |
llvm::generic_gep_type_iterator<llvm::Use const*>::operator!=(llvm::generic_gep_type_iterator<llvm::Use const*> const&) const Line | Count | Source | 61 | 99.3M | bool operator!=(const generic_gep_type_iterator& x) const { | 62 | 99.3M | return !operator==(x); | 63 | 99.3M | } |
|
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 | 813M | Type *getIndexedType() const { |
70 | 813M | if (auto *T = CurTy.dyn_cast<Type *>()) |
71 | 633M | return T; |
72 | 180M | return CurTy.get<StructType *>()->getTypeAtIndex(getOperand()); |
73 | 813M | } llvm::generic_gep_type_iterator<llvm::Use const*>::getIndexedType() const Line | Count | Source | 69 | 738M | Type *getIndexedType() const { | 70 | 738M | if (auto *T = CurTy.dyn_cast<Type *>()) | 71 | 574M | return T; | 72 | 163M | return CurTy.get<StructType *>()->getTypeAtIndex(getOperand()); | 73 | 738M | } |
llvm::generic_gep_type_iterator<llvm::Value* const*>::getIndexedType() const Line | Count | Source | 69 | 45.1M | Type *getIndexedType() const { | 70 | 45.1M | if (auto *T = CurTy.dyn_cast<Type *>()) | 71 | 35.1M | return T; | 72 | 9.95M | return CurTy.get<StructType *>()->getTypeAtIndex(getOperand()); | 73 | 45.1M | } |
llvm::generic_gep_type_iterator<llvm::Value const* const*>::getIndexedType() const Line | Count | Source | 69 | 30.0M | Type *getIndexedType() const { | 70 | 30.0M | if (auto *T = CurTy.dyn_cast<Type *>()) | 71 | 23.2M | return T; | 72 | 6.79M | return CurTy.get<StructType *>()->getTypeAtIndex(getOperand()); | 73 | 30.0M | } |
|
74 | | |
75 | 288M | Value *getOperand() const { return const_cast<Value *>(&**OpIt); } llvm::generic_gep_type_iterator<llvm::Use const*>::getOperand() const Line | Count | Source | 75 | 228M | Value *getOperand() const { return const_cast<Value *>(&**OpIt); } |
llvm::generic_gep_type_iterator<llvm::Value const* const*>::getOperand() const Line | Count | Source | 75 | 6.79M | Value *getOperand() const { return const_cast<Value *>(&**OpIt); } |
llvm::generic_gep_type_iterator<llvm::Value* const*>::getOperand() const Line | Count | Source | 75 | 53.4M | Value *getOperand() const { return const_cast<Value *>(&**OpIt); } |
|
76 | | |
77 | 566M | generic_gep_type_iterator& operator++() { // Preincrement |
78 | 566M | Type *Ty = getIndexedType(); |
79 | 566M | if (auto *STy566M = dyn_cast<SequentialType>(Ty)) { |
80 | 129M | CurTy = STy->getElementType(); |
81 | 129M | NumElements = STy->getNumElements(); |
82 | 129M | } else |
83 | 437M | CurTy = dyn_cast<StructType>(Ty); |
84 | 566M | ++OpIt; |
85 | 566M | return *this; |
86 | 566M | } llvm::generic_gep_type_iterator<llvm::Value* const*>::operator++() Line | Count | Source | 77 | 43.5M | generic_gep_type_iterator& operator++() { // Preincrement | 78 | 43.5M | Type *Ty = getIndexedType(); | 79 | 43.5M | if (auto *STy43.5M = dyn_cast<SequentialType>(Ty)) { | 80 | 12.3M | CurTy = STy->getElementType(); | 81 | 12.3M | NumElements = STy->getNumElements(); | 82 | 12.3M | } else | 83 | 31.2M | CurTy = dyn_cast<StructType>(Ty); | 84 | 43.5M | ++OpIt; | 85 | 43.5M | return *this; | 86 | 43.5M | } |
llvm::generic_gep_type_iterator<llvm::Use const*>::operator++() Line | Count | Source | 77 | 512M | generic_gep_type_iterator& operator++() { // Preincrement | 78 | 512M | Type *Ty = getIndexedType(); | 79 | 512M | if (auto *STy512M = dyn_cast<SequentialType>(Ty)) { | 80 | 115M | CurTy = STy->getElementType(); | 81 | 115M | NumElements = STy->getNumElements(); | 82 | 115M | } else | 83 | 396M | CurTy = dyn_cast<StructType>(Ty); | 84 | 512M | ++OpIt; | 85 | 512M | return *this; | 86 | 512M | } |
llvm::generic_gep_type_iterator<llvm::Value const* const*>::operator++() Line | Count | Source | 77 | 11.0M | generic_gep_type_iterator& operator++() { // Preincrement | 78 | 11.0M | Type *Ty = getIndexedType(); | 79 | 11.0M | if (auto *STy11.0M = dyn_cast<SequentialType>(Ty)) { | 80 | 1.65M | CurTy = STy->getElementType(); | 81 | 1.65M | NumElements = STy->getNumElements(); | 82 | 1.65M | } else | 83 | 9.38M | CurTy = dyn_cast<StructType>(Ty); | 84 | 11.0M | ++OpIt; | 85 | 11.0M | return *this; | 86 | 11.0M | } |
|
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 | 74.5M | bool isStruct() const { return CurTy.is<StructType *>(); } |
108 | 1.30M | bool isSequential() const { return CurTy.is<Type *>(); } |
109 | | |
110 | 86 | StructType *getStructType() const { return CurTy.get<StructType *>(); } |
111 | | |
112 | 466M | StructType *getStructTypeOrNull() const { |
113 | 466M | return CurTy.dyn_cast<StructType *>(); |
114 | 466M | } llvm::generic_gep_type_iterator<llvm::Value const* const*>::getStructTypeOrNull() const Line | Count | Source | 112 | 11.2M | StructType *getStructTypeOrNull() const { | 113 | 11.2M | return CurTy.dyn_cast<StructType *>(); | 114 | 11.2M | } |
llvm::generic_gep_type_iterator<llvm::Value* const*>::getStructTypeOrNull() const Line | Count | Source | 112 | 43.5M | StructType *getStructTypeOrNull() const { | 113 | 43.5M | return CurTy.dyn_cast<StructType *>(); | 114 | 43.5M | } |
llvm::generic_gep_type_iterator<llvm::Use const*>::getStructTypeOrNull() const Line | Count | Source | 112 | 412M | StructType *getStructTypeOrNull() const { | 113 | 412M | return CurTy.dyn_cast<StructType *>(); | 114 | 412M | } |
|
115 | | |
116 | 47.7k | bool isBoundedSequential() const { |
117 | 45.4k | return isSequential() && NumElements != Unbounded; |
118 | 47.7k | } |
119 | | |
120 | 28.2k | uint64_t getSequentialNumElements() const { |
121 | 28.2k | assert(isBoundedSequential()); |
122 | 28.2k | return NumElements; |
123 | 28.2k | } |
124 | | }; |
125 | | |
126 | | using gep_type_iterator = generic_gep_type_iterator<>; |
127 | | |
128 | 201M | inline gep_type_iterator gep_type_begin(const User *GEP) { |
129 | 201M | auto *GEPOp = cast<GEPOperator>(GEP); |
130 | 201M | return gep_type_iterator::begin( |
131 | 201M | GEPOp->getSourceElementType(), |
132 | 201M | GEP->op_begin() + 1); |
133 | 201M | } |
134 | | |
135 | 28.8M | inline gep_type_iterator gep_type_end(const User *GEP) { |
136 | 28.8M | return gep_type_iterator::end(GEP->op_end()); |
137 | 28.8M | } |
138 | | |
139 | 35.1M | inline gep_type_iterator gep_type_begin(const User &GEP) { |
140 | 35.1M | auto &GEPOp = cast<GEPOperator>(GEP); |
141 | 35.1M | return gep_type_iterator::begin( |
142 | 35.1M | GEPOp.getSourceElementType(), |
143 | 35.1M | GEP.op_begin() + 1); |
144 | 35.1M | } |
145 | | |
146 | 2.74M | inline gep_type_iterator gep_type_end(const User &GEP) { |
147 | 2.74M | return gep_type_iterator::end(GEP.op_end()); |
148 | 2.74M | } |
149 | | |
150 | | template<typename T> |
151 | | inline generic_gep_type_iterator<const T *> |
152 | 27.4M | gep_type_begin(Type *Op0, ArrayRef<T> A) { |
153 | 27.4M | return generic_gep_type_iterator<const T *>::begin(Op0, A.begin()); |
154 | 27.4M | } llvm::generic_gep_type_iterator<llvm::Value* const*> llvm::gep_type_begin<llvm::Value*>(llvm::Type*, llvm::ArrayRef<llvm::Value*>) Line | Count | Source | 152 | 21.2M | gep_type_begin(Type *Op0, ArrayRef<T> A) { | 153 | 21.2M | return generic_gep_type_iterator<const T *>::begin(Op0, A.begin()); | 154 | 21.2M | } |
llvm::generic_gep_type_iterator<llvm::Value const* const*> llvm::gep_type_begin<llvm::Value const*>(llvm::Type*, llvm::ArrayRef<llvm::Value const*>) Line | Count | Source | 152 | 6.17M | gep_type_begin(Type *Op0, ArrayRef<T> A) { | 153 | 6.17M | return generic_gep_type_iterator<const T *>::begin(Op0, A.begin()); | 154 | 6.17M | } |
|
155 | | |
156 | | template<typename T> |
157 | | inline generic_gep_type_iterator<const T *> |
158 | 21.2M | gep_type_end(Type * /*Op0*/, ArrayRef<T> A) { |
159 | 21.2M | return generic_gep_type_iterator<const T *>::end(A.end()); |
160 | 21.2M | } |
161 | | |
162 | | } // end namespace llvm |
163 | | |
164 | | #endif // LLVM_IR_GETELEMENTPTRTYPEITERATOR_H |