Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- GetElementPtrTypeIterator.h ------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements an iterator for walking through the types indexed by
  10. // getelementptr instructions.
  11. //
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_IR_GETELEMENTPTRTYPEITERATOR_H
  15. #define LLVM_IR_GETELEMENTPTRTYPEITERATOR_H
  16.  
  17. #include "llvm/ADT/ArrayRef.h"
  18. #include "llvm/ADT/PointerUnion.h"
  19. #include "llvm/IR/DerivedTypes.h"
  20. #include "llvm/IR/Operator.h"
  21. #include "llvm/IR/User.h"
  22. #include "llvm/Support/Casting.h"
  23. #include <cassert>
  24. #include <cstddef>
  25. #include <cstdint>
  26. #include <iterator>
  27.  
  28. namespace llvm {
  29.  
  30. template <typename ItTy = User::const_op_iterator>
  31. class generic_gep_type_iterator {
  32.  
  33.   ItTy OpIt;
  34.   PointerUnion<StructType *, Type *> CurTy;
  35.  
  36.   generic_gep_type_iterator() = default;
  37.  
  38. public:
  39.   using iterator_category = std::forward_iterator_tag;
  40.   using value_type = Type *;
  41.   using difference_type = std::ptrdiff_t;
  42.   using pointer = value_type *;
  43.   using reference = value_type &;
  44.  
  45.   static generic_gep_type_iterator begin(Type *Ty, ItTy It) {
  46.     generic_gep_type_iterator I;
  47.     I.CurTy = Ty;
  48.     I.OpIt = It;
  49.     return I;
  50.   }
  51.  
  52.   static generic_gep_type_iterator end(ItTy It) {
  53.     generic_gep_type_iterator I;
  54.     I.OpIt = It;
  55.     return I;
  56.   }
  57.  
  58.   bool operator==(const generic_gep_type_iterator &x) const {
  59.     return OpIt == x.OpIt;
  60.   }
  61.  
  62.   bool operator!=(const generic_gep_type_iterator &x) const {
  63.     return !operator==(x);
  64.   }
  65.  
  66.   // FIXME: Make this the iterator's operator*() after the 4.0 release.
  67.   // operator*() had a different meaning in earlier releases, so we're
  68.   // temporarily not giving this iterator an operator*() to avoid a subtle
  69.   // semantics break.
  70.   Type *getIndexedType() const {
  71.     if (auto *T = CurTy.dyn_cast<Type *>())
  72.       return T;
  73.     return CurTy.get<StructType *>()->getTypeAtIndex(getOperand());
  74.   }
  75.  
  76.   Value *getOperand() const { return const_cast<Value *>(&**OpIt); }
  77.  
  78.   generic_gep_type_iterator &operator++() { // Preincrement
  79.     Type *Ty = getIndexedType();
  80.     if (auto *ATy = dyn_cast<ArrayType>(Ty))
  81.       CurTy = ATy->getElementType();
  82.     else if (auto *VTy = dyn_cast<VectorType>(Ty))
  83.       CurTy = VTy->getElementType();
  84.     else
  85.       CurTy = dyn_cast<StructType>(Ty);
  86.     ++OpIt;
  87.     return *this;
  88.   }
  89.  
  90.   generic_gep_type_iterator operator++(int) { // Postincrement
  91.     generic_gep_type_iterator tmp = *this;
  92.     ++*this;
  93.     return tmp;
  94.   }
  95.  
  96.   // All of the below API is for querying properties of the "outer type", i.e.
  97.   // the type that contains the indexed type. Most of the time this is just
  98.   // the type that was visited immediately prior to the indexed type, but for
  99.   // the first element this is an unbounded array of the GEP's source element
  100.   // type, for which there is no clearly corresponding IR type (we've
  101.   // historically used a pointer type as the outer type in this case, but
  102.   // pointers will soon lose their element type).
  103.   //
  104.   // FIXME: Most current users of this class are just interested in byte
  105.   // offsets (a few need to know whether the outer type is a struct because
  106.   // they are trying to replace a constant with a variable, which is only
  107.   // legal for arrays, e.g. canReplaceOperandWithVariable in SimplifyCFG.cpp);
  108.   // we should provide a more minimal API here that exposes not much more than
  109.   // that.
  110.  
  111.   bool isStruct() const { return CurTy.is<StructType *>(); }
  112.   bool isSequential() const { return CurTy.is<Type *>(); }
  113.  
  114.   StructType *getStructType() const { return CurTy.get<StructType *>(); }
  115.  
  116.   StructType *getStructTypeOrNull() const {
  117.     return CurTy.dyn_cast<StructType *>();
  118.   }
  119. };
  120.  
  121.   using gep_type_iterator = generic_gep_type_iterator<>;
  122.  
  123.   inline gep_type_iterator gep_type_begin(const User *GEP) {
  124.     auto *GEPOp = cast<GEPOperator>(GEP);
  125.     return gep_type_iterator::begin(
  126.         GEPOp->getSourceElementType(),
  127.         GEP->op_begin() + 1);
  128.   }
  129.  
  130.   inline gep_type_iterator gep_type_end(const User *GEP) {
  131.     return gep_type_iterator::end(GEP->op_end());
  132.   }
  133.  
  134.   inline gep_type_iterator gep_type_begin(const User &GEP) {
  135.     auto &GEPOp = cast<GEPOperator>(GEP);
  136.     return gep_type_iterator::begin(
  137.         GEPOp.getSourceElementType(),
  138.         GEP.op_begin() + 1);
  139.   }
  140.  
  141.   inline gep_type_iterator gep_type_end(const User &GEP) {
  142.     return gep_type_iterator::end(GEP.op_end());
  143.   }
  144.  
  145.   template<typename T>
  146.   inline generic_gep_type_iterator<const T *>
  147.   gep_type_begin(Type *Op0, ArrayRef<T> A) {
  148.     return generic_gep_type_iterator<const T *>::begin(Op0, A.begin());
  149.   }
  150.  
  151.   template<typename T>
  152.   inline generic_gep_type_iterator<const T *>
  153.   gep_type_end(Type * /*Op0*/, ArrayRef<T> A) {
  154.     return generic_gep_type_iterator<const T *>::end(A.end());
  155.   }
  156.  
  157. } // end namespace llvm
  158.  
  159. #endif // LLVM_IR_GETELEMENTPTRTYPEITERATOR_H
  160.