llvm.org GIT mirror llvm / 48973d7 include / llvm / IR / GetElementPtrTypeIterator.h
48973d7

Tree @48973d7 (Download .tar.gz)

GetElementPtrTypeIterator.h @48973d7

bd7cba0
63b3afa
6b54768
 
 
63b3afa
19ed305
 
 
 
 
 
 
bd7cba0
 
19ed305
38d2f63
0611580
0b8c9a8
bd75a92
0b8c9a8
38d2f63
e3e43d9
38d2f63
e3e43d9
38d2f63
19ed305
 
38d2f63
72e606e
43cb041
db125cf
dc6cb60
19ed305
43cb041
0611580
975669a
0611580
dc6cb60
38d2f63
 
 
0611580
bd75a92
0611580
2425f8c
19ed305
 
38d2f63
43cb041
 
2425f8c
19ed305
 
 
63b3afa
2425f8c
19ed305
38d2f63
43cb041
19ed305
 
 
0611580
 
 
 
db125cf
0611580
 
 
79bda7f
 
580991b
19ed305
43cb041
0611580
a705e0e
 
 
0611580
 
2425f8c
63b3afa
19ed305
 
43cb041
63b3afa
19ed305
0611580
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19ed305
 
dc6cb60
43cb041
72e606e
bd75a92
 
 
 
19ed305
38d2f63
72e606e
2425f8c
19ed305
38d2f63
72e606e
bd75a92
 
 
 
c4c6b9e
38d2f63
72e606e
2425f8c
 
43cb041
ca12a21
 
0611580
 
2425f8c
43cb041
ca12a21
 
0611580
ca12a21
c4c6b9e
38d2f63
19ed305
 
38d2f63
//===- GetElementPtrTypeIterator.h ------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements an iterator for walking through the types indexed by
// getelementptr instructions.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_IR_GETELEMENTPTRTYPEITERATOR_H
#define LLVM_IR_GETELEMENTPTRTYPEITERATOR_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/User.h"
#include "llvm/Support/Casting.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iterator>

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 *STy = dyn_cast<SequentialType>(Ty)) {
        CurTy = STy->getElementType();
        NumElements = STy->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<>;

  inline gep_type_iterator gep_type_begin(const User *GEP) {
    auto *GEPOp = cast<GEPOperator>(GEP);
    return gep_type_iterator::begin(
        GEPOp->getSourceElementType(),
        GEP->op_begin() + 1);
  }

  inline gep_type_iterator gep_type_end(const User *GEP) {
    return gep_type_iterator::end(GEP->op_end());
  }

  inline gep_type_iterator gep_type_begin(const User &GEP) {
    auto &GEPOp = cast<GEPOperator>(GEP);
    return gep_type_iterator::begin(
        GEPOp.getSourceElementType(),
        GEP.op_begin() + 1);
  }

  inline gep_type_iterator gep_type_end(const User &GEP) {
    return gep_type_iterator::end(GEP.op_end());
  }

  template<typename T>
  inline generic_gep_type_iterator<const T *>
  gep_type_begin(Type *Op0, ArrayRef<T> A) {
    return generic_gep_type_iterator<const T *>::begin(Op0, A.begin());
  }

  template<typename T>
  inline generic_gep_type_iterator<const T *>
  gep_type_end(Type * /*Op0*/, ArrayRef<T> A) {
    return generic_gep_type_iterator<const T *>::end(A.end());
  }

} // end namespace llvm

#endif // LLVM_IR_GETELEMENTPTRTYPEITERATOR_H