13#ifndef MLIR_SUPPORT_INTERFACESUPPORT_H
14#define MLIR_SUPPORT_INTERFACESUPPORT_H
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/DenseMap.h"
19#include "llvm/Support/TypeName.h"
70template <
typename ConcreteType,
typename ValueT,
typename Traits,
72 template <
typename,
template <
typename>
class>
class BaseTrait>
82 template <
typename T,
typename U>
87 template <
typename ConcreteT>
98 conceptImpl(t ? ConcreteType::getInterfaceFor(t) :
nullptr) {
99 assert((!t || conceptImpl) &&
100 "expected value to provide interface instance");
106 template <
typename T,
107 std::enable_if_t<std::is_base_of<Trait<T>, T>::value> * =
nullptr>
110 conceptImpl(t ? ConcreteType::getInterfaceFor(t) :
nullptr) {
111 assert((!t || conceptImpl) &&
112 "expected value to provide interface instance");
117 : BaseType(t), conceptImpl(const_cast<
Concept *>(conceptImpl)) {
118 assert(!t || ConcreteType::getInterfaceFor(t) == conceptImpl);
126 static bool classof(ValueT t) {
return ConcreteType::getInterfaceFor(t); }
138 Concept *conceptImpl;
149 template <
typename T,
typename... Args>
150 using has_get_interface_id =
decltype(T::getInterfaceID());
151 template <
typename T>
152 using detect_get_interface_id = llvm::is_detected<has_get_interface_id, T>;
155 template <
typename T,
typename... Args>
156 using has_initialize_method =
157 decltype(std::declval<T>().initializeInterfaceConcept(
158 std::declval<InterfaceMap &>()));
159 template <
typename T>
160 using detect_initialize_method = llvm::is_detected<has_initialize_method, T>;
165 template <
typename T,
typename =
void>
166 struct IsConstexprGeneratedModel : std::false_type {};
167 template <
typename T>
168 struct IsConstexprGeneratedModel<T, std::void_t<typename T::GeneratedModel>>
169 : std::bool_constant<std::is_same_v<T, typename T::GeneratedModel> &&
170 std::is_trivially_copy_constructible_v<T>> {};
176 for (
auto &it : interfaces)
178 interfaces = std::move(rhs.interfaces);
182 for (
auto &it : interfaces)
190 template <
typename... Types>
192 constexpr size_t numInterfaces =
193 (
size_t{0} + ... + detect_get_interface_id<Types>::value);
194 if constexpr (numInterfaces == 0) {
198 map.insertPotentialInterfaces<Types...>();
205 template <
typename T>
207 return reinterpret_cast<typename T::Concept *
>(
lookup(T::getInterfaceID()));
214 template <
typename... IfaceModels>
216 (insertModel<IfaceModels>(), ...);
222 template <
typename... Types>
223 void insertPotentialInterfaces() {
224 (insertPotentialInterface<Types>(), ...);
229 template <
typename T>
230 void insertPotentialInterface() {
231 if constexpr (detect_get_interface_id<T>::value)
232 insertModel<typename T::ModelT>();
236 template <
typename InterfaceModel>
245 InterfaceModel *model;
246 if constexpr (IsConstexprGeneratedModel<InterfaceModel>::value) {
247 static constexpr InterfaceModel prototype;
248 model =
new (malloc(
sizeof(InterfaceModel))) InterfaceModel(prototype);
252 model =
new (malloc(
sizeof(InterfaceModel))) InterfaceModel();
256 if constexpr (detect_initialize_method<InterfaceModel>::value)
257 model->initializeInterfaceConcept(*
this);
259 insert(InterfaceModel::Interface::getInterfaceID(), model);
263 void insert(TypeID interfaceId,
void *conceptImpl);
266 static bool compare(TypeID
lhs, TypeID
rhs) {
267 return lhs.getAsOpaquePointer() <
rhs.getAsOpaquePointer();
272 void *
lookup(TypeID
id)
const {
274 llvm::lower_bound(interfaces,
id, [](
const auto &it, TypeID
id) {
275 return compare(it.first,
id);
277 return (it != interfaces.end() && it->first ==
id) ? it->second :
nullptr;
281 SmallVector<std::pair<TypeID, void *>> interfaces;
284template <
typename ConcreteType,
typename ValueT,
typename Traits,
286 template <
typename,
template <
typename>
class>
class BaseTrait>
302struct DenseMapInfo<T, std::enable_if_t<mlir::detail::IsInterface<T>::value>> {
306 return ValueTypeInfo::getHashValue(val);
309 static bool isEqual(T lhs, T rhs) {
return ValueTypeInfo::isEqual(lhs, rhs); }
This class provides an efficient unique identifier for a specific C++ type.
static TypeID get()
Construct a type info object for the given type T.
void insertModels()
Insert the given interface models.
InterfaceMap(InterfaceMap &&)=default
T::Concept * lookup() const
Returns an instance of the concept object for the given interface if it was registered to this map,...
InterfaceMap & operator=(InterfaceMap &&rhs)
static InterfaceMap get()
Construct an InterfaceMap with the given set of template types.
bool contains(TypeID interfaceID) const
Returns true if the interface map contains an interface for the given id.
This class represents an abstract interface.
static bool classof(ValueT t)
Support 'classof' by checking if the given object defines the concrete interface.
Interface(ValueT t, const Concept *conceptImpl)
Constructor for a known concept.
Interface(std::nullptr_t)
Interface(ValueT t, std::nullptr_t)
Constructor for DenseMapInfo's empty key.
Interface(ValueT t=ValueT())
Construct an interface from an instance of the value type.
static TypeID getInterfaceID()
Define an accessor for the ID of this interface.
typename Traits::template ExternalModel< T, U > ExternalModel
Interface< ConcreteType, Attribute, Traits, Attribute, AttributeTrait::TraitBase > InterfaceBase
typename Traits::template FallbackModel< T > FallbackModel
typename Traits::template Model< T > Model
typename Traits::Concept Concept
const Concept * getImpl() const
Get the raw concept in the correct derived concept type.
Interface(T t)
Construct an interface instance from a type that implements this interface's trait.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
decltype(isInterfaceImpl(std::declval< T & >())) is_interface_t
llvm::is_detected< is_interface_t, T > IsInterface
void isInterfaceImpl(Interface< ConcreteType, ValueT, Traits, BaseType, BaseTrait > &)
Include the generated interface declarations.
static unsigned getHashValue(T val)
llvm::DenseMapInfo< typename T::ValueType > ValueTypeInfo
static bool isEqual(T lhs, T rhs)
This is a special trait that registers a given interface with an object.
static TypeID getInterfaceID()
Define an accessor for the ID of this interface.
Model< ConcreteT > ModelT