aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/include/llvm/IR/GetElementPtrTypeIterator.h
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/include/llvm/IR/GetElementPtrTypeIterator.h')
-rw-r--r--contrib/llvm-project/llvm/include/llvm/IR/GetElementPtrTypeIterator.h57
1 files changed, 54 insertions, 3 deletions
diff --git a/contrib/llvm-project/llvm/include/llvm/IR/GetElementPtrTypeIterator.h b/contrib/llvm-project/llvm/include/llvm/IR/GetElementPtrTypeIterator.h
index f3272327c3f8..1092b636e023 100644
--- a/contrib/llvm-project/llvm/include/llvm/IR/GetElementPtrTypeIterator.h
+++ b/contrib/llvm-project/llvm/include/llvm/IR/GetElementPtrTypeIterator.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerUnion.h"
+#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/User.h"
@@ -30,7 +31,39 @@ template <typename ItTy = User::const_op_iterator>
class generic_gep_type_iterator {
ItTy OpIt;
- PointerUnion<StructType *, Type *> CurTy;
+ // We use two different mechanisms to store the type a GEP index applies to.
+ // In some cases, we need to know the outer aggregate type the index is
+ // applied within, e.g. a struct. In such cases, we store the aggregate type
+ // in the iterator, and derive the element type on the fly.
+ //
+ // However, this is not always possible, because for the outermost index there
+ // is no containing type. In such cases, or if the containing type is not
+ // relevant, e.g. for arrays, the element type is stored as Type* in CurTy.
+ //
+ // If CurTy contains a Type* value, this does not imply anything about the
+ // type itself, because it is the element type and not the outer type.
+ // In particular, Type* can be a struct type.
+ //
+ // Consider this example:
+ //
+ // %my.struct = type { i32, [ 4 x float ] }
+ // [...]
+ // %gep = getelementptr %my.struct, ptr %ptr, i32 10, i32 1, 32 3
+ //
+ // Iterating over the indices of this GEP, CurTy will contain the following
+ // values:
+ // * i32 10: The outer index always operates on the GEP value type.
+ // CurTy contains a Type* pointing at `%my.struct`.
+ // * i32 1: This index is within a struct.
+ // CurTy contains a StructType* pointing at `%my.struct`.
+ // * i32 3: This index is within an array. We reuse the "flat" indexing
+ // for arrays which is also used in the top level GEP index.
+ // CurTy contains a Type* pointing at `float`.
+ //
+ // Vectors are handled separately because the layout of vectors is different
+ // for overaligned elements: Vectors are always bit-packed, whereas arrays
+ // respect ABI alignment of the elements.
+ PointerUnion<StructType *, VectorType *, Type *> CurTy;
generic_gep_type_iterator() = default;
@@ -69,6 +102,8 @@ public:
Type *getIndexedType() const {
if (auto *T = dyn_cast_if_present<Type *>(CurTy))
return T;
+ if (auto *VT = dyn_cast_if_present<VectorType *>(CurTy))
+ return VT->getElementType();
return cast<StructType *>(CurTy)->getTypeAtIndex(getOperand());
}
@@ -79,7 +114,7 @@ public:
if (auto *ATy = dyn_cast<ArrayType>(Ty))
CurTy = ATy->getElementType();
else if (auto *VTy = dyn_cast<VectorType>(Ty))
- CurTy = VTy->getElementType();
+ CurTy = VTy;
else
CurTy = dyn_cast<StructType>(Ty);
++OpIt;
@@ -108,7 +143,23 @@ public:
// that.
bool isStruct() const { return isa<StructType *>(CurTy); }
- bool isSequential() const { return isa<Type *>(CurTy); }
+ bool isVector() const { return isa<VectorType *>(CurTy); }
+ bool isSequential() const { return !isStruct(); }
+
+ // For sequential GEP indices (all except those into structs), the index value
+ // can be translated into a byte offset by multiplying with an element stride.
+ // This function returns this stride, which both depends on the element type,
+ // and the containing aggregate type, as vectors always tightly bit-pack their
+ // elements.
+ TypeSize getSequentialElementStride(const DataLayout &DL) const {
+ assert(isSequential());
+ Type *ElemTy = getIndexedType();
+ if (isVector()) {
+ assert(DL.typeSizeEqualsStoreSize(ElemTy) && "Not byte-addressable");
+ return DL.getTypeStoreSize(ElemTy);
+ }
+ return DL.getTypeAllocSize(ElemTy);
+ }
StructType *getStructType() const { return cast<StructType *>(CurTy); }