Home | History | Annotate | Download | only in IR
      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/IR/DerivedTypes.h"
     19 #include "llvm/IR/Operator.h"
     20 #include "llvm/IR/User.h"
     21 #include "llvm/ADT/PointerIntPair.h"
     22 
     23 namespace llvm {
     24   template<typename ItTy = User::const_op_iterator>
     25   class generic_gep_type_iterator
     26     : public std::iterator<std::forward_iterator_tag, Type *, ptrdiff_t> {
     27     typedef std::iterator<std::forward_iterator_tag,
     28                           Type *, ptrdiff_t> super;
     29 
     30     ItTy OpIt;
     31     PointerIntPair<Type *, 1> CurTy;
     32     unsigned AddrSpace;
     33     generic_gep_type_iterator() {}
     34   public:
     35 
     36     static generic_gep_type_iterator begin(Type *Ty, unsigned AddrSpace,
     37                                            ItTy It) {
     38       generic_gep_type_iterator I;
     39       I.CurTy.setPointer(Ty);
     40       I.CurTy.setInt(true);
     41       I.AddrSpace = AddrSpace;
     42       I.OpIt = It;
     43       return I;
     44     }
     45     static generic_gep_type_iterator end(ItTy It) {
     46       generic_gep_type_iterator I;
     47       I.OpIt = It;
     48       return I;
     49     }
     50 
     51     bool operator==(const generic_gep_type_iterator& x) const {
     52       return OpIt == x.OpIt;
     53     }
     54     bool operator!=(const generic_gep_type_iterator& x) const {
     55       return !operator==(x);
     56     }
     57 
     58     Type *operator*() const {
     59       if (CurTy.getInt())
     60         return CurTy.getPointer()->getPointerTo(AddrSpace);
     61       return CurTy.getPointer();
     62     }
     63 
     64     Type *getIndexedType() const {
     65       if (CurTy.getInt())
     66         return CurTy.getPointer();
     67       CompositeType *CT = cast<CompositeType>(CurTy.getPointer());
     68       return CT->getTypeAtIndex(getOperand());
     69     }
     70 
     71     // This is a non-standard operator->.  It allows you to call methods on the
     72     // current type directly.
     73     Type *operator->() const { return operator*(); }
     74 
     75     Value *getOperand() const { return const_cast<Value *>(&**OpIt); }
     76 
     77     generic_gep_type_iterator& operator++() {   // Preincrement
     78       if (CurTy.getInt()) {
     79         CurTy.setInt(false);
     80       } else if (CompositeType *CT =
     81                      dyn_cast<CompositeType>(CurTy.getPointer())) {
     82         CurTy.setPointer(CT->getTypeAtIndex(getOperand()));
     83       } else {
     84         CurTy.setPointer(nullptr);
     85       }
     86       ++OpIt;
     87       return *this;
     88     }
     89 
     90     generic_gep_type_iterator operator++(int) { // Postincrement
     91       generic_gep_type_iterator tmp = *this; ++*this; return tmp;
     92     }
     93   };
     94 
     95   typedef generic_gep_type_iterator<> gep_type_iterator;
     96 
     97   inline gep_type_iterator gep_type_begin(const User *GEP) {
     98     auto *GEPOp = cast<GEPOperator>(GEP);
     99     return gep_type_iterator::begin(
    100         GEPOp->getSourceElementType(),
    101         cast<PointerType>(GEPOp->getPointerOperandType()->getScalarType())
    102             ->getAddressSpace(),
    103         GEP->op_begin() + 1);
    104   }
    105   inline gep_type_iterator gep_type_end(const User *GEP) {
    106     return gep_type_iterator::end(GEP->op_end());
    107   }
    108   inline gep_type_iterator gep_type_begin(const User &GEP) {
    109     auto &GEPOp = cast<GEPOperator>(GEP);
    110     return gep_type_iterator::begin(
    111         GEPOp.getSourceElementType(),
    112         cast<PointerType>(GEPOp.getPointerOperandType()->getScalarType())
    113             ->getAddressSpace(),
    114         GEP.op_begin() + 1);
    115   }
    116   inline gep_type_iterator gep_type_end(const User &GEP) {
    117     return gep_type_iterator::end(GEP.op_end());
    118   }
    119 
    120   template<typename T>
    121   inline generic_gep_type_iterator<const T *>
    122   gep_type_begin(Type *Op0, unsigned AS, ArrayRef<T> A) {
    123     return generic_gep_type_iterator<const T *>::begin(Op0, AS, A.begin());
    124   }
    125 
    126   template<typename T>
    127   inline generic_gep_type_iterator<const T *>
    128   gep_type_end(Type * /*Op0*/, unsigned /*AS*/, ArrayRef<T> A) {
    129     return generic_gep_type_iterator<const T *>::end(A.end());
    130   }
    131 } // end namespace llvm
    132 
    133 #endif
    134