//===- InterfaceSupport.h - MLIR Interface Support Classes ------*- 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 defines several support classes for defining interfaces. // //===----------------------------------------------------------------------===// #ifndef MLIR_SUPPORT_INTERFACESUPPORT_H #define MLIR_SUPPORT_INTERFACESUPPORT_H #include "mlir/Support/TypeID.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/TypeName.h" namespace mlir { namespace detail { //===----------------------------------------------------------------------===// // Interface //===----------------------------------------------------------------------===// /// This class represents an abstract interface. An interface is a simplified /// mechanism for attaching concept based polymorphism to a class hierarchy. An /// interface is comprised of two components: /// * The derived interface class: This is what users interact with, and invoke /// methods on. /// * An interface `Trait` class: This is the class that is attached to the /// object implementing the interface. It is the mechanism with which models /// are specialized. /// /// Derived interfaces types must provide the following template types: /// * ConcreteType: The CRTP derived type. /// * ValueT: The opaque type the derived interface operates on. For example /// `Operation*` for operation interfaces, or `Attribute` for /// attribute interfaces. /// * Traits: A class that contains definitions for a 'Concept' and a 'Model' /// class. The 'Concept' class defines an abstract virtual interface, /// where as the 'Model' class implements this interface for a /// specific derived T type. Both of these classes *must* not contain /// non-static data. A simple example is shown below: /// /// ```c++ /// struct ExampleInterfaceTraits { /// struct Concept { /// virtual unsigned getNumInputs(T t) const = 0; /// }; /// template <typename DerivedT> class Model { /// unsigned getNumInputs(T t) const final { /// return cast<DerivedT>(t).getNumInputs(); /// } /// }; /// }; /// ``` /// /// * BaseType: A desired base type for the interface. This is a class /// that provides specific functionality for the `ValueT` /// value. For instance the specific `Op` that will wrap the /// `Operation*` for an `OpInterface`. /// * BaseTrait: The base type for the interface trait. This is the base class /// to use for the interface trait that will be attached to each /// instance of `ValueT` that implements this interface. /// template <typename ConcreteType, typename ValueT, typename Traits, typename BaseType, template <typename, template <typename> class> class BaseTrait> class Interface : public BaseType { … }; //===----------------------------------------------------------------------===// // InterfaceMap //===----------------------------------------------------------------------===// /// Template utility that computes the number of elements within `T` that /// satisfy the given predicate. template <template <class> class Pred, size_t N, typename... Ts> struct count_if_t_impl : public std::integral_constant<size_t, N> { … }; count_if_t_impl<Pred, N, T, Us...>; count_if_t; /// This class provides an efficient mapping between a given `Interface` type, /// and a particular implementation of its concept. class InterfaceMap { … }; template <typename ConcreteType, typename ValueT, typename Traits, typename BaseType, template <typename, template <typename> class> class BaseTrait> void isInterfaceImpl( Interface<ConcreteType, ValueT, Traits, BaseType, BaseTrait> &); is_interface_t; IsInterface; } // namespace detail } // namespace mlir namespace llvm { DenseMapInfo<T, std::enable_if_t<mlir::detail::IsInterface<T>::value>>; } // namespace llvm #endif