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