//===- AttrTypeSubElements.h - Attr and Type SubElements -------*- 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 contains utilities for querying the sub elements of an attribute or // type. // //===----------------------------------------------------------------------===// #ifndef MLIR_IR_ATTRTYPESUBELEMENTS_H #define MLIR_IR_ATTRTYPESUBELEMENTS_H #include "mlir/IR/MLIRContext.h" #include "mlir/IR/Visitors.h" #include "mlir/Support/CyclicReplacerCache.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include <optional> namespace mlir { class Attribute; class Type; //===----------------------------------------------------------------------===// /// AttrTypeWalker //===----------------------------------------------------------------------===// /// This class provides a utility for walking attributes/types, and their sub /// elements. Multiple walk functions may be registered. class AttrTypeWalker { … }; //===----------------------------------------------------------------------===// /// AttrTypeReplacer //===----------------------------------------------------------------------===// namespace detail { /// This class provides a base utility for replacing attributes/types, and their /// sub elements. Multiple replacement functions may be registered. /// /// This base utility is uncached. Users can choose between two cached versions /// of this replacer: /// * For non-cyclic replacer logic, use `AttrTypeReplacer`. /// * For cyclic replacer logic, use `CyclicAttrTypeReplacer`. /// /// Concrete implementations implement the following `replace` entry functions: /// * Attribute replace(Attribute attr); /// * Type replace(Type type); template <typename Concrete> class AttrTypeReplacerBase { … }; } // namespace detail /// This is an attribute/type replacer that is naively cached. It is best used /// when the replacer logic is guaranteed to not contain cycles. Otherwise, any /// re-occurrence of an in-progress element will be skipped. class AttrTypeReplacer : public detail::AttrTypeReplacerBase<AttrTypeReplacer> { … }; /// This is an attribute/type replacer that supports custom handling of cycles /// in the replacer logic. In addition to registering replacer functions, it /// allows registering cycle-breaking functions in the same style. class CyclicAttrTypeReplacer : public detail::AttrTypeReplacerBase<CyclicAttrTypeReplacer> { … }; //===----------------------------------------------------------------------===// /// AttrTypeSubElementHandler //===----------------------------------------------------------------------===// /// This class is used by AttrTypeSubElementHandler instances to walking sub /// attributes and types. class AttrTypeImmediateSubElementWalker { … }; /// This class is used by AttrTypeSubElementHandler instances to process sub /// element replacements. template <typename T> class AttrTypeSubElementReplacements { … }; AttrSubElementReplacements; TypeSubElementReplacements; /// This class provides support for interacting with the /// SubElementInterfaces for different types of parameters. An /// implementation of this class should be provided for any parameter class /// that may contain an attribute or type. There are two main methods of /// this class that need to be implemented: /// /// - walk /// /// This method should traverse into any sub elements of the parameter /// using the provided walker, or by invoking handlers for sub-types. /// /// - replace /// /// This method should extract any necessary sub elements using the /// provided replacer, or by invoking handlers for sub-types. The new /// post-replacement parameter value should be returned. /// template <typename T, typename Enable = void> struct AttrTypeSubElementHandler { … }; /// Detect if any of the given parameter types has a sub-element handler. namespace detail { has_default_sub_element_handler_t; } // namespace detail has_sub_attr_or_type_v; /// Implementation for derived Attributes and Types. AttrTypeSubElementHandler<T, std::enable_if_t<std::is_base_of_v<Attribute, T> || std::is_base_of_v<Type, T>>>; /// Implementation for derived ArrayRef. AttrTypeSubElementHandler<ArrayRef<T>, std::enable_if_t<has_sub_attr_or_type_v<T>>>; /// Implementation for Tuple. AttrTypeSubElementHandler<std::tuple<Ts...>, std::enable_if_t<has_sub_attr_or_type_v<Ts...>>>; namespace detail { template <typename T> struct is_tuple : public std::false_type { … }; is_tuple<std::tuple<Ts...>>; template <typename T> struct is_pair : public std::false_type { … }; is_pair<std::pair<Ts...>>; has_get_method; has_get_as_key; /// This function provides the underlying implementation for the /// SubElementInterface walk method, using the key type of the derived /// attribute/type to interact with the individual parameters. template <typename T> void walkImmediateSubElementsImpl(T derived, function_ref<void(Attribute)> walkAttrsFn, function_ref<void(Type)> walkTypesFn) { … } /// This function invokes the proper `get` method for a type `T` with the given /// values. template <typename T, typename... Ts> auto constructSubElementReplacement(MLIRContext *ctx, Ts &&...params) { … } /// This function provides the underlying implementation for the /// SubElementInterface replace method, using the key type of the derived /// attribute/type to interact with the individual parameters. template <typename T> auto replaceImmediateSubElementsImpl(T derived, ArrayRef<Attribute> &replAttrs, ArrayRef<Type> &replTypes) { … } } // namespace detail } // namespace mlir #endif // MLIR_IR_ATTRTYPESUBELEMENTS_H