diff options
Diffstat (limited to 'llvm/include/llvm/IR/GetElementPtrTypeIterator.h')
-rw-r--r-- | llvm/include/llvm/IR/GetElementPtrTypeIterator.h | 206 |
1 files changed, 106 insertions, 100 deletions
diff --git a/llvm/include/llvm/IR/GetElementPtrTypeIterator.h b/llvm/include/llvm/IR/GetElementPtrTypeIterator.h index 6293305a2639..ed854e458da2 100644 --- a/llvm/include/llvm/IR/GetElementPtrTypeIterator.h +++ b/llvm/include/llvm/IR/GetElementPtrTypeIterator.h @@ -27,106 +27,112 @@ namespace llvm { - template<typename ItTy = User::const_op_iterator> - class generic_gep_type_iterator - : public std::iterator<std::forward_iterator_tag, Type *, ptrdiff_t> { - using super = std::iterator<std::forward_iterator_tag, Type *, ptrdiff_t>; - - ItTy OpIt; - PointerUnion<StructType *, Type *> CurTy; - enum : uint64_t { Unbounded = -1ull }; - uint64_t NumElements = Unbounded; - - generic_gep_type_iterator() = default; - - public: - static generic_gep_type_iterator begin(Type *Ty, ItTy It) { - generic_gep_type_iterator I; - I.CurTy = Ty; - I.OpIt = It; - return I; - } - - static generic_gep_type_iterator end(ItTy It) { - generic_gep_type_iterator I; - I.OpIt = It; - return I; - } - - bool operator==(const generic_gep_type_iterator& x) const { - return OpIt == x.OpIt; - } - - bool operator!=(const generic_gep_type_iterator& x) const { - return !operator==(x); - } - - // FIXME: Make this the iterator's operator*() after the 4.0 release. - // operator*() had a different meaning in earlier releases, so we're - // temporarily not giving this iterator an operator*() to avoid a subtle - // semantics break. - Type *getIndexedType() const { - if (auto *T = CurTy.dyn_cast<Type *>()) - return T; - return CurTy.get<StructType *>()->getTypeAtIndex(getOperand()); - } - - Value *getOperand() const { return const_cast<Value *>(&**OpIt); } - - generic_gep_type_iterator& operator++() { // Preincrement - Type *Ty = getIndexedType(); - if (auto *ATy = dyn_cast<ArrayType>(Ty)) { - CurTy = ATy->getElementType(); - NumElements = ATy->getNumElements(); - } else if (auto *VTy = dyn_cast<VectorType>(Ty)) { - CurTy = VTy->getElementType(); - if (isa<ScalableVectorType>(VTy)) - NumElements = Unbounded; - else - NumElements = cast<FixedVectorType>(VTy)->getNumElements(); - } else - CurTy = dyn_cast<StructType>(Ty); - ++OpIt; - return *this; - } - - generic_gep_type_iterator operator++(int) { // Postincrement - generic_gep_type_iterator tmp = *this; ++*this; return tmp; - } - - // All of the below API is for querying properties of the "outer type", i.e. - // the type that contains the indexed type. Most of the time this is just - // the type that was visited immediately prior to the indexed type, but for - // the first element this is an unbounded array of the GEP's source element - // type, for which there is no clearly corresponding IR type (we've - // historically used a pointer type as the outer type in this case, but - // pointers will soon lose their element type). - // - // FIXME: Most current users of this class are just interested in byte - // offsets (a few need to know whether the outer type is a struct because - // they are trying to replace a constant with a variable, which is only - // legal for arrays, e.g. canReplaceOperandWithVariable in SimplifyCFG.cpp); - // we should provide a more minimal API here that exposes not much more than - // that. - - bool isStruct() const { return CurTy.is<StructType *>(); } - bool isSequential() const { return CurTy.is<Type *>(); } - - StructType *getStructType() const { return CurTy.get<StructType *>(); } - - StructType *getStructTypeOrNull() const { - return CurTy.dyn_cast<StructType *>(); - } - - bool isBoundedSequential() const { - return isSequential() && NumElements != Unbounded; - } - - uint64_t getSequentialNumElements() const { - assert(isBoundedSequential()); - return NumElements; - } - }; +template <typename ItTy = User::const_op_iterator> +class generic_gep_type_iterator { + + ItTy OpIt; + PointerUnion<StructType *, Type *> CurTy; + enum : uint64_t { Unbounded = -1ull }; + uint64_t NumElements = Unbounded; + + generic_gep_type_iterator() = default; + +public: + using iterator_category = std::forward_iterator_tag; + using value_type = Type *; + using difference_type = std::ptrdiff_t; + using pointer = value_type *; + using reference = value_type &; + + static generic_gep_type_iterator begin(Type *Ty, ItTy It) { + generic_gep_type_iterator I; + I.CurTy = Ty; + I.OpIt = It; + return I; + } + + static generic_gep_type_iterator end(ItTy It) { + generic_gep_type_iterator I; + I.OpIt = It; + return I; + } + + bool operator==(const generic_gep_type_iterator &x) const { + return OpIt == x.OpIt; + } + + bool operator!=(const generic_gep_type_iterator &x) const { + return !operator==(x); + } + + // FIXME: Make this the iterator's operator*() after the 4.0 release. + // operator*() had a different meaning in earlier releases, so we're + // temporarily not giving this iterator an operator*() to avoid a subtle + // semantics break. + Type *getIndexedType() const { + if (auto *T = CurTy.dyn_cast<Type *>()) + return T; + return CurTy.get<StructType *>()->getTypeAtIndex(getOperand()); + } + + Value *getOperand() const { return const_cast<Value *>(&**OpIt); } + + generic_gep_type_iterator &operator++() { // Preincrement + Type *Ty = getIndexedType(); + if (auto *ATy = dyn_cast<ArrayType>(Ty)) { + CurTy = ATy->getElementType(); + NumElements = ATy->getNumElements(); + } else if (auto *VTy = dyn_cast<VectorType>(Ty)) { + CurTy = VTy->getElementType(); + if (isa<ScalableVectorType>(VTy)) + NumElements = Unbounded; + else + NumElements = cast<FixedVectorType>(VTy)->getNumElements(); + } else + CurTy = dyn_cast<StructType>(Ty); + ++OpIt; + return *this; + } + + generic_gep_type_iterator operator++(int) { // Postincrement + generic_gep_type_iterator tmp = *this; + ++*this; + return tmp; + } + + // All of the below API is for querying properties of the "outer type", i.e. + // the type that contains the indexed type. Most of the time this is just + // the type that was visited immediately prior to the indexed type, but for + // the first element this is an unbounded array of the GEP's source element + // type, for which there is no clearly corresponding IR type (we've + // historically used a pointer type as the outer type in this case, but + // pointers will soon lose their element type). + // + // FIXME: Most current users of this class are just interested in byte + // offsets (a few need to know whether the outer type is a struct because + // they are trying to replace a constant with a variable, which is only + // legal for arrays, e.g. canReplaceOperandWithVariable in SimplifyCFG.cpp); + // we should provide a more minimal API here that exposes not much more than + // that. + + bool isStruct() const { return CurTy.is<StructType *>(); } + bool isSequential() const { return CurTy.is<Type *>(); } + + StructType *getStructType() const { return CurTy.get<StructType *>(); } + + StructType *getStructTypeOrNull() const { + return CurTy.dyn_cast<StructType *>(); + } + + bool isBoundedSequential() const { + return isSequential() && NumElements != Unbounded; + } + + uint64_t getSequentialNumElements() const { + assert(isBoundedSequential()); + return NumElements; + } +}; using gep_type_iterator = generic_gep_type_iterator<>; |