LLVM  mainline
GetElementPtrTypeIterator.h
Go to the documentation of this file.
00001 //===- GetElementPtrTypeIterator.h ------------------------------*- C++ -*-===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements an iterator for walking through the types indexed by
00011 // getelementptr instructions.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #ifndef LLVM_IR_GETELEMENTPTRTYPEITERATOR_H
00016 #define LLVM_IR_GETELEMENTPTRTYPEITERATOR_H
00017 
00018 #include "llvm/IR/DerivedTypes.h"
00019 #include "llvm/IR/User.h"
00020 
00021 namespace llvm {
00022   template<typename ItTy = User::const_op_iterator>
00023   class generic_gep_type_iterator
00024     : public std::iterator<std::forward_iterator_tag, Type *, ptrdiff_t> {
00025     typedef std::iterator<std::forward_iterator_tag,
00026                           Type *, ptrdiff_t> super;
00027 
00028     ItTy OpIt;
00029     Type *CurTy;
00030     generic_gep_type_iterator() {}
00031   public:
00032 
00033     static generic_gep_type_iterator begin(Type *Ty, ItTy It) {
00034       generic_gep_type_iterator I;
00035       I.CurTy = Ty;
00036       I.OpIt = It;
00037       return I;
00038     }
00039     static generic_gep_type_iterator end(ItTy It) {
00040       generic_gep_type_iterator I;
00041       I.CurTy = nullptr;
00042       I.OpIt = It;
00043       return I;
00044     }
00045 
00046     bool operator==(const generic_gep_type_iterator& x) const {
00047       return OpIt == x.OpIt;
00048     }
00049     bool operator!=(const generic_gep_type_iterator& x) const {
00050       return !operator==(x);
00051     }
00052 
00053     Type *operator*() const {
00054       return CurTy;
00055     }
00056 
00057     Type *getIndexedType() const {
00058       CompositeType *CT = cast<CompositeType>(CurTy);
00059       return CT->getTypeAtIndex(getOperand());
00060     }
00061 
00062     // This is a non-standard operator->.  It allows you to call methods on the
00063     // current type directly.
00064     Type *operator->() const { return operator*(); }
00065 
00066     Value *getOperand() const { return *OpIt; }
00067 
00068     generic_gep_type_iterator& operator++() {   // Preincrement
00069       if (CompositeType *CT = dyn_cast<CompositeType>(CurTy)) {
00070         CurTy = CT->getTypeAtIndex(getOperand());
00071       } else {
00072         CurTy = nullptr;
00073       }
00074       ++OpIt;
00075       return *this;
00076     }
00077 
00078     generic_gep_type_iterator operator++(int) { // Postincrement
00079       generic_gep_type_iterator tmp = *this; ++*this; return tmp;
00080     }
00081   };
00082 
00083   typedef generic_gep_type_iterator<> gep_type_iterator;
00084 
00085   inline gep_type_iterator gep_type_begin(const User *GEP) {
00086     return gep_type_iterator::begin
00087       (GEP->getOperand(0)->getType()->getScalarType(), GEP->op_begin()+1);
00088   }
00089   inline gep_type_iterator gep_type_end(const User *GEP) {
00090     return gep_type_iterator::end(GEP->op_end());
00091   }
00092   inline gep_type_iterator gep_type_begin(const User &GEP) {
00093     return gep_type_iterator::begin
00094       (GEP.getOperand(0)->getType()->getScalarType(), GEP.op_begin()+1);
00095   }
00096   inline gep_type_iterator gep_type_end(const User &GEP) {
00097     return gep_type_iterator::end(GEP.op_end());
00098   }
00099 
00100   template<typename T>
00101   inline generic_gep_type_iterator<const T *>
00102   gep_type_begin(Type *Op0, ArrayRef<T> A) {
00103     return generic_gep_type_iterator<const T *>::begin(Op0, A.begin());
00104   }
00105 
00106   template<typename T>
00107   inline generic_gep_type_iterator<const T *>
00108   gep_type_end(Type * /*Op0*/, ArrayRef<T> A) {
00109     return generic_gep_type_iterator<const T *>::end(A.end());
00110   }
00111 } // end namespace llvm
00112 
00113 #endif