LCOV - code coverage report
Current view: top level - include/llvm/IR - GetElementPtrTypeIterator.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 34 34 100.0 %
Date: 2017-09-14 15:23:50 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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   100021580 :     generic_gep_type_iterator() = default;
      42             : 
      43             :   public:
      44             :     static generic_gep_type_iterator begin(Type *Ty, ItTy It) {
      45    31517278 :       generic_gep_type_iterator I;
      46    63034556 :       I.CurTy = Ty;
      47    31517278 :       I.OpIt = It;
      48             :       return I;
      49             :     }
      50             : 
      51             :     static generic_gep_type_iterator end(ItTy It) {
      52    18493512 :       generic_gep_type_iterator I;
      53    18493512 :       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             : 
      61             :     bool operator!=(const generic_gep_type_iterator& x) const {
      62    55738311 :       return !operator==(x);
      63             :     }
      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    96551665 :     Type *getIndexedType() const {
      70   188666955 :       if (auto *T = CurTy.dyn_cast<Type *>())
      71             :         return T;
      72    13309125 :       return CurTy.get<StructType *>()->getTypeAtIndex(getOperand());
      73             :     }
      74             : 
      75    41500430 :     Value *getOperand() const { return const_cast<Value *>(&**OpIt); }
      76             : 
      77    64158314 :     generic_gep_type_iterator& operator++() {   // Preincrement
      78    64158314 :       Type *Ty = getIndexedType();
      79    28410384 :       if (auto *STy = dyn_cast<SequentialType>(Ty)) {
      80    56820768 :         CurTy = STy->getElementType();
      81    28410384 :         NumElements = STy->getNumElements();
      82             :       } else
      83    71495860 :         CurTy = dyn_cast<StructType>(Ty);
      84    64158314 :       ++OpIt;
      85    64158314 :       return *this;
      86             :     }
      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     4970860 :     bool isStruct() const { return CurTy.is<StructType *>(); }
     108      354924 :     bool isSequential() const { return CurTy.is<Type *>(); }
     109             : 
     110         172 :     StructType *getStructType() const { return CurTy.get<StructType *>(); }
     111             : 
     112             :     StructType *getStructTypeOrNull() const {
     113    52429100 :       return CurTy.dyn_cast<StructType *>();
     114             :     }
     115             : 
     116             :     bool isBoundedSequential() const {
     117        1182 :       return isSequential() && NumElements != Unbounded;
     118             :     }
     119             : 
     120             :     uint64_t getSequentialNumElements() const {
     121             :       assert(isBoundedSequential());
     122             :       return NumElements;
     123             :     }
     124             :   };
     125             : 
     126             :   using gep_type_iterator = generic_gep_type_iterator<>;
     127             : 
     128    20118665 :   inline gep_type_iterator gep_type_begin(const User *GEP) {
     129    20118665 :     auto *GEPOp = cast<GEPOperator>(GEP);
     130             :     return gep_type_iterator::begin(
     131             :         GEPOp->getSourceElementType(),
     132    40237330 :         GEP->op_begin() + 1);
     133             :   }
     134             : 
     135             :   inline gep_type_iterator gep_type_end(const User *GEP) {
     136    16871030 :     return gep_type_iterator::end(GEP->op_end());
     137             :   }
     138             : 
     139     1433723 :   inline gep_type_iterator gep_type_begin(const User &GEP) {
     140     1433723 :     auto &GEPOp = cast<GEPOperator>(GEP);
     141             :     return gep_type_iterator::begin(
     142             :         GEPOp.getSourceElementType(),
     143     2867446 :         GEP.op_begin() + 1);
     144             :   }
     145             : 
     146             :   inline gep_type_iterator gep_type_end(const User &GEP) {
     147      823568 :     return gep_type_iterator::end(GEP.op_end());
     148             :   }
     149             : 
     150             :   template<typename T>
     151             :   inline generic_gep_type_iterator<const T *>
     152             :   gep_type_begin(Type *Op0, ArrayRef<T> A) {
     153    19929780 :     return generic_gep_type_iterator<const T *>::begin(Op0, A.begin());
     154             :   }
     155             : 
     156             :   template<typename T>
     157             :   inline generic_gep_type_iterator<const T *>
     158             :   gep_type_end(Type * /*Op0*/, ArrayRef<T> A) {
     159    19292426 :     return generic_gep_type_iterator<const T *>::end(A.end());
     160             :   }
     161             : 
     162             : } // end namespace llvm
     163             : 
     164             : #endif // LLVM_IR_GETELEMENTPTRTYPEITERATOR_H

Generated by: LCOV version 1.13