/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\ |* *| |* Interface Declarations *| |* *| |* Automatically generated file, do not edit! *| |* *| \*===----------------------------------------------------------------------===*/ namespace mlir { /// This interface is used for attributes that have a type. The type of an /// attribute is understood to represent the type of the data contained in the /// attribute and is often used as the type of a value with this data. class TypedAttr; } // namespace mlir namespace mlir { /// This interface allows an attribute to expose a blob of data without more /// information. The data must be stored so that it can be accessed as a /// contiguous ArrayRef. class BlobAttr; } // namespace mlir namespace mlir { /// This interface is used for attributes that contain the constant elements of /// a tensor or vector type. It allows for opaquely interacting with the /// elements of the underlying attribute, and most importantly allows for /// accessing the element values (including iteration) in any of the C++ data /// types supported by the underlying attribute. /// /// An attribute implementing this interface can expose the supported data types /// in two steps: /// /// * Define the set of iterable C++ data types: /// /// An attribute may define the set of iterable types by providing a definition /// of tuples `ContiguousIterableTypesT` and/or `NonContiguousIterableTypesT`. /// /// - `ContiguousIterableTypesT` should contain types which can be iterated /// contiguously. A contiguous range is an array-like range, such as /// ArrayRef, where all of the elements are layed out sequentially in memory. /// /// - `NonContiguousIterableTypesT` should contain types which can not be /// iterated contiguously. A non-contiguous range implies no contiguity, /// whose elements may even be materialized when indexing, such as the case /// for a mapped_range. /// /// As an example, consider an attribute that only contains i64 elements, with /// the elements being stored within an ArrayRef. This attribute could /// potentially define the iterable types as so: /// /// ```c++ /// using ContiguousIterableTypesT = std::tuple; /// using NonContiguousIterableTypesT = std::tuple; /// ``` /// /// * Provide a `FailureOr try_value_begin_impl(OverloadToken) const` /// overload for each iterable type /// /// These overloads should return an iterator to the start of the range for the /// respective iterable type or fail if the type cannot be iterated. Consider /// the example i64 elements attribute described in the previous section. This /// attribute may define the value_begin_impl overloads like so: /// /// ```c++ /// /// Provide begin iterators for the various iterable types. /// /// * uint64_t /// FailureOr /// value_begin_impl(OverloadToken) const { /// return getElements().begin(); /// } /// /// * APInt /// auto value_begin_impl(OverloadToken) const { /// auto it = llvm::map_range(getElements(), [=](uint64_t value) { /// return llvm::APInt(/*numBits=*/64, value); /// }).begin(); /// return FailureOr(std::move(it)); /// } /// /// * Attribute /// auto value_begin_impl(OverloadToken) const { /// mlir::Type elementType = getShapedType().getElementType(); /// auto it = llvm::map_range(getElements(), [=](uint64_t value) { /// return mlir::IntegerAttr::get(elementType, /// llvm::APInt(/*numBits=*/64, value)); /// }).begin(); /// return FailureOr(std::move(it)); /// } /// ``` /// /// After the above, ElementsAttr will now be able to iterate over elements /// using each of the registered iterable data types: /// /// ```c++ /// ElementsAttr attr = myI64ElementsAttr; /// /// // We can access value ranges for the data types via `getValues`. /// for (uint64_t value : attr.getValues()) /// ...; /// for (llvm::APInt value : attr.getValues()) /// ...; /// for (mlir::IntegerAttr value : attr.getValues()) /// ...; /// /// // We can also access the value iterators directly. /// auto it = attr.value_begin(), e = attr.value_end(); /// for (; it != e; ++it) { /// uint64_t value = *it; /// ... /// } /// ``` /// /// ElementsAttr also supports failable access to iterators and ranges. This /// allows for safely checking if the attribute supports the data type, and can /// also allow for code to have fast paths for native data types. /// /// ```c++ /// // Using `tryGetValues`, we can also safely handle when the attribute /// // doesn't support the data type. /// if (auto range = attr.tryGetValues()) { /// for (uint64_t value : *range) /// ...; /// return; /// } /// /// // We can also access the begin iterator safely, by using `try_value_begin`. /// if (auto safeIt = attr.try_value_begin()) { /// auto it = *safeIt, e = attr.value_end(); /// for (; it != e; ++it) { /// uint64_t value = *it; /// ... /// } /// return; /// } /// ``` class ElementsAttr; } // namespace mlir namespace mlir { /// This interface is used for attributes that can represent the MemRef type's /// layout semantics, such as dimension order in the memory, strides and offsets. /// Such a layout attribute should be representable as a /// [semi-affine map](Affine.md/#semi-affine-maps). /// /// Note: the MemRef type's layout is assumed to represent simple strided buffer /// layout. For more complicated case, like sparse storage buffers, /// it is preferable to use a separate type with a more specific layout, rather /// than introducing extra complexity to the builtin MemRef type. class MemRefLayoutAttrInterface; } // namespace mlir namespace mlir { /// This interface is used for attributes that have a type. The type of an /// attribute is understood to represent the type of the data contained in the /// attribute and is often used as the type of a value with this data. namespace detail { struct TypedAttrInterfaceTraits { struct Concept { /// The methods defined by the interface. ::mlir::Type (*getType)(const Concept *impl, ::mlir::Attribute ); }; template class Model : public Concept { public: using Interface = ::mlir::TypedAttr; Model() : Concept{getType} {} static inline ::mlir::Type getType(const Concept *impl, ::mlir::Attribute tablegen_opaque_val); }; template class FallbackModel : public Concept { public: using Interface = ::mlir::TypedAttr; FallbackModel() : Concept{getType} {} static inline ::mlir::Type getType(const Concept *impl, ::mlir::Attribute tablegen_opaque_val); }; template class ExternalModel : public FallbackModel { public: using ConcreteEntity = ConcreteAttr; }; }; template struct TypedAttrTrait; } // namespace detail class TypedAttr : public ::mlir::AttributeInterface { public: using ::mlir::AttributeInterface::AttributeInterface; template struct Trait : public detail::TypedAttrTrait {}; /// Get the attribute's type ::mlir::Type getType() const; }; } // namespace mlir namespace mlir { /// This interface allows an attribute to expose a blob of data without more /// information. The data must be stored so that it can be accessed as a /// contiguous ArrayRef. namespace detail { struct BlobAttrInterfaceTraits { struct Concept { /// The methods defined by the interface. ::llvm::ArrayRef (*getData)(const Concept *impl, ::mlir::Attribute ); }; template class Model : public Concept { public: using Interface = ::mlir::BlobAttr; Model() : Concept{getData} {} static inline ::llvm::ArrayRef getData(const Concept *impl, ::mlir::Attribute tablegen_opaque_val); }; template class FallbackModel : public Concept { public: using Interface = ::mlir::BlobAttr; FallbackModel() : Concept{getData} {} static inline ::llvm::ArrayRef getData(const Concept *impl, ::mlir::Attribute tablegen_opaque_val); }; template class ExternalModel : public FallbackModel { public: using ConcreteEntity = ConcreteAttr; }; }; template struct BlobAttrTrait; } // namespace detail class BlobAttr : public ::mlir::AttributeInterface { public: using ::mlir::AttributeInterface::AttributeInterface; template struct Trait : public detail::BlobAttrTrait {}; /// Get the attribute's data ::llvm::ArrayRef getData() const; }; } // namespace mlir namespace mlir { /// This interface is used for attributes that contain the constant elements of /// a tensor or vector type. It allows for opaquely interacting with the /// elements of the underlying attribute, and most importantly allows for /// accessing the element values (including iteration) in any of the C++ data /// types supported by the underlying attribute. /// /// An attribute implementing this interface can expose the supported data types /// in two steps: /// /// * Define the set of iterable C++ data types: /// /// An attribute may define the set of iterable types by providing a definition /// of tuples `ContiguousIterableTypesT` and/or `NonContiguousIterableTypesT`. /// /// - `ContiguousIterableTypesT` should contain types which can be iterated /// contiguously. A contiguous range is an array-like range, such as /// ArrayRef, where all of the elements are layed out sequentially in memory. /// /// - `NonContiguousIterableTypesT` should contain types which can not be /// iterated contiguously. A non-contiguous range implies no contiguity, /// whose elements may even be materialized when indexing, such as the case /// for a mapped_range. /// /// As an example, consider an attribute that only contains i64 elements, with /// the elements being stored within an ArrayRef. This attribute could /// potentially define the iterable types as so: /// /// ```c++ /// using ContiguousIterableTypesT = std::tuple; /// using NonContiguousIterableTypesT = std::tuple; /// ``` /// /// * Provide a `FailureOr try_value_begin_impl(OverloadToken) const` /// overload for each iterable type /// /// These overloads should return an iterator to the start of the range for the /// respective iterable type or fail if the type cannot be iterated. Consider /// the example i64 elements attribute described in the previous section. This /// attribute may define the value_begin_impl overloads like so: /// /// ```c++ /// /// Provide begin iterators for the various iterable types. /// /// * uint64_t /// FailureOr /// value_begin_impl(OverloadToken) const { /// return getElements().begin(); /// } /// /// * APInt /// auto value_begin_impl(OverloadToken) const { /// auto it = llvm::map_range(getElements(), [=](uint64_t value) { /// return llvm::APInt(/*numBits=*/64, value); /// }).begin(); /// return FailureOr(std::move(it)); /// } /// /// * Attribute /// auto value_begin_impl(OverloadToken) const { /// mlir::Type elementType = getShapedType().getElementType(); /// auto it = llvm::map_range(getElements(), [=](uint64_t value) { /// return mlir::IntegerAttr::get(elementType, /// llvm::APInt(/*numBits=*/64, value)); /// }).begin(); /// return FailureOr(std::move(it)); /// } /// ``` /// /// After the above, ElementsAttr will now be able to iterate over elements /// using each of the registered iterable data types: /// /// ```c++ /// ElementsAttr attr = myI64ElementsAttr; /// /// // We can access value ranges for the data types via `getValues`. /// for (uint64_t value : attr.getValues()) /// ...; /// for (llvm::APInt value : attr.getValues()) /// ...; /// for (mlir::IntegerAttr value : attr.getValues()) /// ...; /// /// // We can also access the value iterators directly. /// auto it = attr.value_begin(), e = attr.value_end(); /// for (; it != e; ++it) { /// uint64_t value = *it; /// ... /// } /// ``` /// /// ElementsAttr also supports failable access to iterators and ranges. This /// allows for safely checking if the attribute supports the data type, and can /// also allow for code to have fast paths for native data types. /// /// ```c++ /// // Using `tryGetValues`, we can also safely handle when the attribute /// // doesn't support the data type. /// if (auto range = attr.tryGetValues()) { /// for (uint64_t value : *range) /// ...; /// return; /// } /// /// // We can also access the begin iterator safely, by using `try_value_begin`. /// if (auto safeIt = attr.try_value_begin()) { /// auto it = *safeIt, e = attr.value_end(); /// for (; it != e; ++it) { /// uint64_t value = *it; /// ... /// } /// return; /// } /// ``` namespace detail { struct ElementsAttrInterfaceTraits { struct Concept { /// The methods defined by the interface. ::mlir::FailureOr<::mlir::detail::ElementsAttrIndexer> (*getValuesImpl)(const Concept *impl, ::mlir::Attribute , ::mlir::TypeID); bool (*isSplat)(const Concept *impl, ::mlir::Attribute ); ::mlir::ShapedType (*getShapedType)(const Concept *impl, ::mlir::Attribute ); /// The base classes of this interface. const ::mlir::TypedAttr::Concept *implTypedAttr = nullptr; void initializeInterfaceConcept(::mlir::detail::InterfaceMap &interfaceMap) { implTypedAttr = interfaceMap.lookup<::mlir::TypedAttr>(); assert(implTypedAttr && "`::mlir::ElementsAttr` expected its base interface `::mlir::TypedAttr` to be registered"); } }; template class Model : public Concept { public: using Interface = ::mlir::ElementsAttr; Model() : Concept{getValuesImpl, isSplat, getShapedType} {} static inline ::mlir::FailureOr<::mlir::detail::ElementsAttrIndexer> getValuesImpl(const Concept *impl, ::mlir::Attribute tablegen_opaque_val, ::mlir::TypeID elementID); static inline bool isSplat(const Concept *impl, ::mlir::Attribute tablegen_opaque_val); static inline ::mlir::ShapedType getShapedType(const Concept *impl, ::mlir::Attribute tablegen_opaque_val); }; template class FallbackModel : public Concept { public: using Interface = ::mlir::ElementsAttr; FallbackModel() : Concept{getValuesImpl, isSplat, getShapedType} {} static inline ::mlir::FailureOr<::mlir::detail::ElementsAttrIndexer> getValuesImpl(const Concept *impl, ::mlir::Attribute tablegen_opaque_val, ::mlir::TypeID elementID); static inline bool isSplat(const Concept *impl, ::mlir::Attribute tablegen_opaque_val); static inline ::mlir::ShapedType getShapedType(const Concept *impl, ::mlir::Attribute tablegen_opaque_val); }; template class ExternalModel : public FallbackModel { public: using ConcreteEntity = ConcreteAttr; ::mlir::FailureOr<::mlir::detail::ElementsAttrIndexer> getValuesImpl(::mlir::Attribute tablegen_opaque_val, ::mlir::TypeID elementID) const; bool isSplat(::mlir::Attribute tablegen_opaque_val) const; ::mlir::ShapedType getShapedType(::mlir::Attribute tablegen_opaque_val) const; }; }; template struct ElementsAttrTrait; } // namespace detail class ElementsAttr : public ::mlir::AttributeInterface { public: using ::mlir::AttributeInterface::AttributeInterface; template struct Trait : public detail::ElementsAttrTrait {}; /// This method returns an opaque range indexer for the given elementID, which /// corresponds to a desired C++ element data type. Returns the indexer if the /// attribute supports the given data type, failure otherwise. ::mlir::FailureOr<::mlir::detail::ElementsAttrIndexer> getValuesImpl(::mlir::TypeID elementID) const; /// Returns true if the attribute elements correspond to a splat, i.e. that /// all elements of the attribute are the same value. bool isSplat() const; /// Returns the shaped type of the elements attribute. ::mlir::ShapedType getShapedType() const; template using iterator = detail::ElementsAttrIterator; template using iterator_range = detail::ElementsAttrRange>; //===------------------------------------------------------------------===// // Accessors //===------------------------------------------------------------------===// /// Return the element type of this ElementsAttr. Type getElementType() const { return getElementType(*this); } static Type getElementType(ElementsAttr elementsAttr); /// Return if the given 'index' refers to a valid element in this attribute. bool isValidIndex(ArrayRef index) const { return isValidIndex(*this, index); } static bool isValidIndex(ShapedType type, ArrayRef index); static bool isValidIndex(ElementsAttr elementsAttr, ArrayRef index); /// Return the 1 dimensional flattened row-major index from the given /// multi-dimensional index. uint64_t getFlattenedIndex(ArrayRef index) const { return getFlattenedIndex(*this, index); } static uint64_t getFlattenedIndex(Type type, ArrayRef index); static uint64_t getFlattenedIndex(ElementsAttr elementsAttr, ArrayRef index) { return getFlattenedIndex(elementsAttr.getShapedType(), index); } /// Returns the number of elements held by this attribute. int64_t getNumElements() const { return getNumElements(*this); } static int64_t getNumElements(ElementsAttr elementsAttr); //===------------------------------------------------------------------===// // Value Iteration //===------------------------------------------------------------------===// template using DerivedAttrValueCheckT = std::enable_if_t::value && !std::is_same::value>; template using DefaultValueCheckT = std::enable_if_t::value || !std::is_base_of::value, ResultT>; /// Return the splat value for this attribute. This asserts that the /// attribute corresponds to a splat. template T getSplatValue() const { assert(isSplat() && "expected splat attribute"); return *value_begin(); } /// Return the elements of this attribute as a value of type 'T'. template DefaultValueCheckT> getValues() const { return {getShapedType(), value_begin(), value_end()}; } template DefaultValueCheckT> value_begin() const; template DefaultValueCheckT> value_end() const { return iterator({}, size()); } /// Return the held element values a range of T, where T is a derived /// attribute type. template using DerivedAttrValueIterator = llvm::mapped_iterator, T (*)(Attribute)>; template using DerivedAttrValueIteratorRange = detail::ElementsAttrRange>; template > DerivedAttrValueIteratorRange getValues() const { auto castFn = [](Attribute attr) { return ::llvm::cast(attr); }; return {getShapedType(), llvm::map_range(getValues(), static_cast(castFn))}; } template > DerivedAttrValueIterator value_begin() const { return getValues().begin(); } template > DerivedAttrValueIterator value_end() const { return {value_end(), nullptr}; } //===------------------------------------------------------------------===// // Failable Value Iteration /// If this attribute supports iterating over element values of type `T`, /// return the iterable range. Otherwise, return std::nullopt. template DefaultValueCheckT>> tryGetValues() const { if (std::optional> beginIt = try_value_begin()) return iterator_range(getShapedType(), *beginIt, value_end()); return std::nullopt; } template DefaultValueCheckT>> try_value_begin() const; /// If this attribute supports iterating over element values of type `T`, /// return the iterable range. Otherwise, return std::nullopt. template > std::optional> tryGetValues() const { auto values = tryGetValues(); if (!values) return std::nullopt; auto castFn = [](Attribute attr) { return ::llvm::cast(attr); }; return DerivedAttrValueIteratorRange( getShapedType(), llvm::map_range(*values, static_cast(castFn)) ); } template > std::optional> try_value_begin() const { if (auto values = tryGetValues()) return values->begin(); return std::nullopt; } /// Return the number of elements held by this attribute. int64_t size() const { return getNumElements(); } /// Return if the attribute holds no elements. bool empty() const { return size() == 0; } //===----------------------------------------------------------------===// // Inherited from ::mlir::TypedAttr //===----------------------------------------------------------------===// operator ::mlir::TypedAttr () const { if (!*this) return nullptr; return ::mlir::TypedAttr(*this, getImpl()->implTypedAttr); } /// Get the attribute's type ::mlir::Type getType() const; }; } // namespace mlir namespace mlir { /// This interface is used for attributes that can represent the MemRef type's /// layout semantics, such as dimension order in the memory, strides and offsets. /// Such a layout attribute should be representable as a /// [semi-affine map](Affine.md/#semi-affine-maps). /// /// Note: the MemRef type's layout is assumed to represent simple strided buffer /// layout. For more complicated case, like sparse storage buffers, /// it is preferable to use a separate type with a more specific layout, rather /// than introducing extra complexity to the builtin MemRef type. namespace detail { struct MemRefLayoutAttrInterfaceInterfaceTraits { struct Concept { /// The methods defined by the interface. ::mlir::AffineMap (*getAffineMap)(const Concept *impl, ::mlir::Attribute ); bool (*isIdentity)(const Concept *impl, ::mlir::Attribute ); ::llvm::LogicalResult (*verifyLayout)(const Concept *impl, ::mlir::Attribute , ::llvm::ArrayRef, ::llvm::function_ref<::mlir::InFlightDiagnostic()>); ::llvm::LogicalResult (*getStridesAndOffset)(const Concept *impl, ::mlir::Attribute , ::llvm::ArrayRef, ::llvm::SmallVectorImpl&, int64_t&); }; template class Model : public Concept { public: using Interface = ::mlir::MemRefLayoutAttrInterface; Model() : Concept{getAffineMap, isIdentity, verifyLayout, getStridesAndOffset} {} static inline ::mlir::AffineMap getAffineMap(const Concept *impl, ::mlir::Attribute tablegen_opaque_val); static inline bool isIdentity(const Concept *impl, ::mlir::Attribute tablegen_opaque_val); static inline ::llvm::LogicalResult verifyLayout(const Concept *impl, ::mlir::Attribute tablegen_opaque_val, ::llvm::ArrayRef shape, ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError); static inline ::llvm::LogicalResult getStridesAndOffset(const Concept *impl, ::mlir::Attribute tablegen_opaque_val, ::llvm::ArrayRef shape, ::llvm::SmallVectorImpl& strides, int64_t& offset); }; template class FallbackModel : public Concept { public: using Interface = ::mlir::MemRefLayoutAttrInterface; FallbackModel() : Concept{getAffineMap, isIdentity, verifyLayout, getStridesAndOffset} {} static inline ::mlir::AffineMap getAffineMap(const Concept *impl, ::mlir::Attribute tablegen_opaque_val); static inline bool isIdentity(const Concept *impl, ::mlir::Attribute tablegen_opaque_val); static inline ::llvm::LogicalResult verifyLayout(const Concept *impl, ::mlir::Attribute tablegen_opaque_val, ::llvm::ArrayRef shape, ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError); static inline ::llvm::LogicalResult getStridesAndOffset(const Concept *impl, ::mlir::Attribute tablegen_opaque_val, ::llvm::ArrayRef shape, ::llvm::SmallVectorImpl& strides, int64_t& offset); }; template class ExternalModel : public FallbackModel { public: using ConcreteEntity = ConcreteAttr; bool isIdentity(::mlir::Attribute tablegen_opaque_val) const; ::llvm::LogicalResult verifyLayout(::mlir::Attribute tablegen_opaque_val, ::llvm::ArrayRef shape, ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) const; ::llvm::LogicalResult getStridesAndOffset(::mlir::Attribute tablegen_opaque_val, ::llvm::ArrayRef shape, ::llvm::SmallVectorImpl&strides, int64_t&offset) const; }; }; template struct MemRefLayoutAttrInterfaceTrait; } // namespace detail class MemRefLayoutAttrInterface : public ::mlir::AttributeInterface { public: using ::mlir::AttributeInterface::AttributeInterface; template struct Trait : public detail::MemRefLayoutAttrInterfaceTrait {}; /// Get the MemRef layout as an AffineMap, the method must not return NULL ::mlir::AffineMap getAffineMap() const; /// Return true if this attribute represents the identity layout bool isIdentity() const; /// Check if the current layout is applicable to the provided shape ::llvm::LogicalResult verifyLayout(::llvm::ArrayRef shape, ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) const; /// Return the strides (using ShapedType::kDynamic for the dynamic case) /// that this layout corresponds to into `strides` and `offset` if such exist /// and can be determined from a combination of the layout and the given /// `shape`. If these strides cannot be inferred, return failure(). /// The values of `strides` and `offset` are undefined on failure. ::llvm::LogicalResult getStridesAndOffset(::llvm::ArrayRef shape, ::llvm::SmallVectorImpl& strides, int64_t& offset) const; }; } // namespace mlir namespace mlir::detail { template struct TypedAttrTrait : public ::mlir::AttributeInterface::Trait { }; } // namespace mlir::detail namespace mlir::detail { template struct BlobAttrTrait : public ::mlir::AttributeInterface::Trait { }; } // namespace mlir::detail namespace mlir::detail { template struct ElementsAttrTrait : public ::mlir::AttributeInterface::Trait { /// This method returns an opaque range indexer for the given elementID, which /// corresponds to a desired C++ element data type. Returns the indexer if the /// attribute supports the given data type, failure otherwise. ::mlir::FailureOr<::mlir::detail::ElementsAttrIndexer> getValuesImpl(::mlir::TypeID elementID) const { auto result = getValueImpl( (typename ConcreteAttr::ContiguousIterableTypesT *)nullptr, elementID, /*isContiguous=*/std::true_type()); if (succeeded(result)) return std::move(result); return getValueImpl( (typename ConcreteAttr::NonContiguousIterableTypesT *)nullptr, elementID, /*isContiguous=*/std::false_type()); } /// Returns true if the attribute elements correspond to a splat, i.e. that /// all elements of the attribute are the same value. bool isSplat() const { // By default, only check for a single element splat. return (*static_cast(this)).getNumElements() == 1; } /// Returns the shaped type of the elements attribute. ::mlir::ShapedType getShapedType() const { return (*static_cast(this)).getType(); } // By default, no types are iterable. using ContiguousIterableTypesT = std::tuple<>; using NonContiguousIterableTypesT = std::tuple<>; //===------------------------------------------------------------------===// // Accessors //===------------------------------------------------------------------===// /// Return the element type of this ElementsAttr. Type getElementType() const { return ::mlir::ElementsAttr::getElementType((*static_cast(this))); } /// Returns the number of elements held by this attribute. int64_t getNumElements() const { return ::mlir::ElementsAttr::getNumElements((*static_cast(this))); } /// Return if the given 'index' refers to a valid element in this attribute. bool isValidIndex(ArrayRef index) const { return ::mlir::ElementsAttr::isValidIndex((*static_cast(this)), index); } protected: /// Returns the 1-dimensional flattened row-major index from the given /// multi-dimensional index. uint64_t getFlattenedIndex(ArrayRef index) const { return ::mlir::ElementsAttr::getFlattenedIndex((*static_cast(this)), index); } //===------------------------------------------------------------------===// // Value Iteration Internals //===------------------------------------------------------------------===// protected: /// This class is used to allow specifying function overloads for different /// types, without actually taking the types as parameters. This avoids the /// need to build complicated SFINAE to select specific overloads. template struct OverloadToken {}; private: /// This function unpacks the types within a given tuple and then forwards /// on to the unwrapped variant. template auto getValueImpl(std::tuple *, ::mlir::TypeID elementID, IsContiguousT isContiguous) const { return getValueImpl(elementID, isContiguous); } /// Check to see if the given `elementID` matches the current type `T`. If /// it does, build a value result using the current type. If it doesn't, /// keep looking for the desired type. template auto getValueImpl(::mlir::TypeID elementID, IsContiguousT isContiguous) const { if (::mlir::TypeID::get() == elementID) return buildValueResult(isContiguous); return getValueImpl(elementID, isContiguous); } /// Bottom out case for no matching type. template ::mlir::FailureOr<::mlir::detail::ElementsAttrIndexer> getValueImpl(::mlir::TypeID, IsContiguousT) const { return failure(); } /// Build an indexer for the given type `T`, which is represented via a /// contiguous range. template ::mlir::FailureOr<::mlir::detail::ElementsAttrIndexer> buildValueResult( /*isContiguous*/std::true_type) const { if ((*static_cast(this)).empty()) { return ::mlir::detail::ElementsAttrIndexer::contiguous( /*isSplat=*/false, nullptr); } auto valueIt = (*static_cast(this)).try_value_begin_impl(OverloadToken()); if (::mlir::failed(valueIt)) return ::mlir::failure(); return ::mlir::detail::ElementsAttrIndexer::contiguous( (*static_cast(this)).isSplat(), &**valueIt); } /// Build an indexer for the given type `T`, which is represented via a /// non-contiguous range. template ::mlir::FailureOr<::mlir::detail::ElementsAttrIndexer> buildValueResult( /*isContiguous*/std::false_type) const { auto valueIt = (*static_cast(this)).try_value_begin_impl(OverloadToken()); if (::mlir::failed(valueIt)) return ::mlir::failure(); return ::mlir::detail::ElementsAttrIndexer::nonContiguous( (*static_cast(this)).isSplat(), *valueIt); } public: //===------------------------------------------------------------------===// // Value Iteration //===------------------------------------------------------------------===// /// The iterator for the given element type T. template using iterator = decltype(std::declval().template value_begin()); /// The iterator range over the given element T. template using iterator_range = decltype(std::declval().template getValues()); /// Return an iterator to the first element of this attribute as a value of /// type `T`. template auto value_begin() const { return *(*static_cast(this)).try_value_begin_impl(OverloadToken()); } /// Return the elements of this attribute as a value of type 'T'. template auto getValues() const { auto beginIt = (*static_cast(this)).template value_begin(); return detail::ElementsAttrRange( (*static_cast(this)).getType(), beginIt, std::next(beginIt, size())); } /// Return the number of elements held by this attribute. int64_t size() const { return getNumElements(); } /// Return if the attribute holds no elements. bool empty() const { return size() == 0; } }; } // namespace mlir::detail namespace mlir::detail { template struct MemRefLayoutAttrInterfaceTrait : public ::mlir::AttributeInterface::Trait { /// Return true if this attribute represents the identity layout bool isIdentity() const { return (*static_cast(this)).getAffineMap().isIdentity(); } /// Check if the current layout is applicable to the provided shape ::llvm::LogicalResult verifyLayout(::llvm::ArrayRef shape, ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) const { return ::mlir::detail::verifyAffineMapAsLayout((*static_cast(this)).getAffineMap(), shape, emitError); } /// Return the strides (using ShapedType::kDynamic for the dynamic case) /// that this layout corresponds to into `strides` and `offset` if such exist /// and can be determined from a combination of the layout and the given /// `shape`. If these strides cannot be inferred, return failure(). /// The values of `strides` and `offset` are undefined on failure. ::llvm::LogicalResult getStridesAndOffset(::llvm::ArrayRef shape, ::llvm::SmallVectorImpl& strides, int64_t& offset) const { return ::mlir::detail::getAffineMapStridesAndOffset( (*static_cast(this)).getAffineMap(), shape, strides, offset); } }; } // namespace mlir::detail namespace mlir { template ::mlir::Type detail::TypedAttrInterfaceTraits::Model::getType(const Concept *impl, ::mlir::Attribute tablegen_opaque_val) { return (::llvm::cast(tablegen_opaque_val)).getType(); } template ::mlir::Type detail::TypedAttrInterfaceTraits::FallbackModel::getType(const Concept *impl, ::mlir::Attribute tablegen_opaque_val) { return static_cast(impl)->getType(tablegen_opaque_val); } } // namespace mlir namespace mlir { template ::llvm::ArrayRef detail::BlobAttrInterfaceTraits::Model::getData(const Concept *impl, ::mlir::Attribute tablegen_opaque_val) { return (::llvm::cast(tablegen_opaque_val)).getData(); } template ::llvm::ArrayRef detail::BlobAttrInterfaceTraits::FallbackModel::getData(const Concept *impl, ::mlir::Attribute tablegen_opaque_val) { return static_cast(impl)->getData(tablegen_opaque_val); } } // namespace mlir namespace mlir { template ::mlir::FailureOr<::mlir::detail::ElementsAttrIndexer> detail::ElementsAttrInterfaceTraits::Model::getValuesImpl(const Concept *impl, ::mlir::Attribute tablegen_opaque_val, ::mlir::TypeID elementID) { return (::llvm::cast(tablegen_opaque_val)).getValuesImpl(elementID); } template bool detail::ElementsAttrInterfaceTraits::Model::isSplat(const Concept *impl, ::mlir::Attribute tablegen_opaque_val) { return (::llvm::cast(tablegen_opaque_val)).isSplat(); } template ::mlir::ShapedType detail::ElementsAttrInterfaceTraits::Model::getShapedType(const Concept *impl, ::mlir::Attribute tablegen_opaque_val) { return (::llvm::cast(tablegen_opaque_val)).getShapedType(); } template ::mlir::FailureOr<::mlir::detail::ElementsAttrIndexer> detail::ElementsAttrInterfaceTraits::FallbackModel::getValuesImpl(const Concept *impl, ::mlir::Attribute tablegen_opaque_val, ::mlir::TypeID elementID) { return static_cast(impl)->getValuesImpl(tablegen_opaque_val, elementID); } template bool detail::ElementsAttrInterfaceTraits::FallbackModel::isSplat(const Concept *impl, ::mlir::Attribute tablegen_opaque_val) { return static_cast(impl)->isSplat(tablegen_opaque_val); } template ::mlir::ShapedType detail::ElementsAttrInterfaceTraits::FallbackModel::getShapedType(const Concept *impl, ::mlir::Attribute tablegen_opaque_val) { return static_cast(impl)->getShapedType(tablegen_opaque_val); } template ::mlir::FailureOr<::mlir::detail::ElementsAttrIndexer> detail::ElementsAttrInterfaceTraits::ExternalModel::getValuesImpl(::mlir::Attribute tablegen_opaque_val, ::mlir::TypeID elementID) const { auto result = getValueImpl( (typename ConcreteAttr::ContiguousIterableTypesT *)nullptr, elementID, /*isContiguous=*/std::true_type()); if (succeeded(result)) return std::move(result); return getValueImpl( (typename ConcreteAttr::NonContiguousIterableTypesT *)nullptr, elementID, /*isContiguous=*/std::false_type()); } template bool detail::ElementsAttrInterfaceTraits::ExternalModel::isSplat(::mlir::Attribute tablegen_opaque_val) const { // By default, only check for a single element splat. return (::llvm::cast(tablegen_opaque_val)).getNumElements() == 1; } template ::mlir::ShapedType detail::ElementsAttrInterfaceTraits::ExternalModel::getShapedType(::mlir::Attribute tablegen_opaque_val) const { return (::llvm::cast(tablegen_opaque_val)).getType(); } } // namespace mlir namespace mlir { template ::mlir::AffineMap detail::MemRefLayoutAttrInterfaceInterfaceTraits::Model::getAffineMap(const Concept *impl, ::mlir::Attribute tablegen_opaque_val) { return (::llvm::cast(tablegen_opaque_val)).getAffineMap(); } template bool detail::MemRefLayoutAttrInterfaceInterfaceTraits::Model::isIdentity(const Concept *impl, ::mlir::Attribute tablegen_opaque_val) { return (::llvm::cast(tablegen_opaque_val)).isIdentity(); } template ::llvm::LogicalResult detail::MemRefLayoutAttrInterfaceInterfaceTraits::Model::verifyLayout(const Concept *impl, ::mlir::Attribute tablegen_opaque_val, ::llvm::ArrayRef shape, ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) { return (::llvm::cast(tablegen_opaque_val)).verifyLayout(shape, emitError); } template ::llvm::LogicalResult detail::MemRefLayoutAttrInterfaceInterfaceTraits::Model::getStridesAndOffset(const Concept *impl, ::mlir::Attribute tablegen_opaque_val, ::llvm::ArrayRef shape, ::llvm::SmallVectorImpl& strides, int64_t& offset) { return (::llvm::cast(tablegen_opaque_val)).getStridesAndOffset(shape, strides, offset); } template ::mlir::AffineMap detail::MemRefLayoutAttrInterfaceInterfaceTraits::FallbackModel::getAffineMap(const Concept *impl, ::mlir::Attribute tablegen_opaque_val) { return static_cast(impl)->getAffineMap(tablegen_opaque_val); } template bool detail::MemRefLayoutAttrInterfaceInterfaceTraits::FallbackModel::isIdentity(const Concept *impl, ::mlir::Attribute tablegen_opaque_val) { return static_cast(impl)->isIdentity(tablegen_opaque_val); } template ::llvm::LogicalResult detail::MemRefLayoutAttrInterfaceInterfaceTraits::FallbackModel::verifyLayout(const Concept *impl, ::mlir::Attribute tablegen_opaque_val, ::llvm::ArrayRef shape, ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) { return static_cast(impl)->verifyLayout(tablegen_opaque_val, shape, emitError); } template ::llvm::LogicalResult detail::MemRefLayoutAttrInterfaceInterfaceTraits::FallbackModel::getStridesAndOffset(const Concept *impl, ::mlir::Attribute tablegen_opaque_val, ::llvm::ArrayRef shape, ::llvm::SmallVectorImpl& strides, int64_t& offset) { return static_cast(impl)->getStridesAndOffset(tablegen_opaque_val, shape, strides, offset); } template bool detail::MemRefLayoutAttrInterfaceInterfaceTraits::ExternalModel::isIdentity(::mlir::Attribute tablegen_opaque_val) const { return (::llvm::cast(tablegen_opaque_val)).getAffineMap().isIdentity(); } template ::llvm::LogicalResult detail::MemRefLayoutAttrInterfaceInterfaceTraits::ExternalModel::verifyLayout(::mlir::Attribute tablegen_opaque_val, ::llvm::ArrayRef shape, ::llvm::function_ref<::mlir::InFlightDiagnostic()> emitError) const { return ::mlir::detail::verifyAffineMapAsLayout((::llvm::cast(tablegen_opaque_val)).getAffineMap(), shape, emitError); } template ::llvm::LogicalResult detail::MemRefLayoutAttrInterfaceInterfaceTraits::ExternalModel::getStridesAndOffset(::mlir::Attribute tablegen_opaque_val, ::llvm::ArrayRef shape, ::llvm::SmallVectorImpl&strides, int64_t&offset) const { return ::mlir::detail::getAffineMapStridesAndOffset( (::llvm::cast(tablegen_opaque_val)).getAffineMap(), shape, strides, offset); } } // namespace mlir