//===- 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 class Model { /// unsigned getNumInputs(T t) const final { /// return cast(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 class> class BaseTrait> class Interface : public BaseType { public: using Concept = typename Traits::Concept; template using Model = typename Traits::template Model; template using FallbackModel = typename Traits::template FallbackModel; using InterfaceBase = Interface; template using ExternalModel = typename Traits::template ExternalModel; using ValueType = ValueT; /// This is a special trait that registers a given interface with an object. template struct Trait : public BaseTrait { using ModelT = Model; /// Define an accessor for the ID of this interface. static TypeID getInterfaceID() { return TypeID::get(); } }; /// Construct an interface from an instance of the value type. explicit Interface(ValueT t = ValueT()) : BaseType(t), conceptImpl(t ? ConcreteType::getInterfaceFor(t) : nullptr) { assert((!t || conceptImpl) && "expected value to provide interface instance"); } Interface(std::nullptr_t) : BaseType(ValueT()), conceptImpl(nullptr) {} /// Construct an interface instance from a type that implements this /// interface's trait. template , T>::value> * = nullptr> Interface(T t) : BaseType(t), conceptImpl(t ? ConcreteType::getInterfaceFor(t) : nullptr) { assert((!t || conceptImpl) && "expected value to provide interface instance"); } /// Constructor for a known concept. Interface(ValueT t, const Concept *conceptImpl) : BaseType(t), conceptImpl(const_cast(conceptImpl)) { assert(!t || ConcreteType::getInterfaceFor(t) == conceptImpl); } /// Constructor for DenseMapInfo's empty key. Interface(ValueT t, std::nullptr_t) : BaseType(t), conceptImpl(nullptr) {} /// Support 'classof' by checking if the given object defines the concrete /// interface. static bool classof(ValueT t) { return ConcreteType::getInterfaceFor(t); } /// Define an accessor for the ID of this interface. static TypeID getInterfaceID() { return TypeID::get(); } protected: /// Get the raw concept in the correct derived concept type. const Concept *getImpl() const { return conceptImpl; } Concept *getImpl() { return conceptImpl; } private: /// A pointer to the impl concept object. Concept *conceptImpl; }; //===----------------------------------------------------------------------===// // InterfaceMap //===----------------------------------------------------------------------===// /// Template utility that computes the number of elements within `T` that /// satisfy the given predicate. template