13 #ifndef MLIR_IR_STORAGEUNIQUERSUPPORT_H
14 #define MLIR_IR_STORAGEUNIQUERSUPPORT_H
21 #include "llvm/ADT/FunctionExtras.h"
24 class InFlightDiagnostic;
32 llvm::unique_function<InFlightDiagnostic()>
34 llvm::unique_function<InFlightDiagnostic()>
43 template <
typename ConcreteType,
template <
typename>
class TraitType>
52 auto *trait =
static_cast<const TraitType<ConcreteType> *
>(
this);
53 return *
static_cast<const ConcreteType *
>(trait);
57 namespace StorageUserTrait {
63 template <
typename ConcreteType>
71 namespace storage_user_base_impl {
74 template <
template <
typename T>
class... Traits>
76 TypeID traitIDs[] = {TypeID::get<Traits>()...};
77 for (
unsigned i = 0, e =
sizeof...(Traits); i != e; ++i)
78 if (traitIDs[i] == traitID)
93 template <
typename ConcreteT,
typename BaseT,
typename StorageT,
94 typename UniquerT,
template <
typename T>
class... Traits>
109 template <
typename T>
111 static_assert(std::is_convertible<ConcreteT, T>::value,
112 "casting from a non-convertible type");
119 return detail::InterfaceMap::template get<Traits<ConcreteT>...>();
136 llvm::cast<ConcreteT>(instance), walkAttrsFn, walkTypesFn);
146 llvm::cast<ConcreteT>(instance), replAttrs, replTypes);
154 template <
typename... IfaceModels>
156 typename ConcreteT::AbstractTy *
abstract =
157 ConcreteT::AbstractTy::lookupMutable(TypeID::get<ConcreteT>(),
160 llvm::report_fatal_error(
"Registering an interface for an attribute/type "
161 "that is not itself registered.");
165 abstract->getDialect(), abstract->getTypeID(),
166 IfaceModels::Interface::getInterfaceID()),
169 (checkInterfaceTarget<IfaceModels>(), ...);
170 abstract->interfaceMap.template insertModels<IfaceModels...>();
176 template <
typename... Args>
181 return UniquerT::template get<ConcreteT>(ctx, std::forward<Args>(args)...);
188 template <
typename... Args>
191 std::forward<Args>(args)...);
197 template <
typename... Args>
201 if (failed(ConcreteT::verifyInvariants(emitErrorFn, args...)))
203 return UniquerT::template get<ConcreteT>(ctx, args...);
208 return ConcreteT((
const typename BaseT::ImplType *)ptr);
217 template <
typename... Args>
221 "The `mutate` function expects mutable trait "
222 "(e.g. TypeTrait::IsMutable) to be attached on parent.");
224 std::forward<Args>(args)...);
228 template <
typename... Args>
235 template <
typename T>
236 using has_concrete_entity_t =
typename T::ConcreteEntity;
242 template <
typename T,
243 bool = llvm::is_detected<has_concrete_entity_t, T>::value>
244 struct IfaceTargetOrConcreteT {
245 using type =
typename T::ConcreteEntity;
247 template <
typename T>
248 struct IfaceTargetOrConcreteT<T, false> {
249 using type = ConcreteT;
255 template <
typename T>
256 static void checkInterfaceTarget() {
257 static_assert(std::is_base_of<
typename IfaceTargetOrConcreteT<T>::type,
259 "attaching an interface to the wrong attribute/type kind");
static MLIRContext * getContext(OpFoldResult val)
Attributes are known-constant values of operations.
This class represents a diagnostic that is inflight and set to be reported.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
This class provides an efficient unique identifier for a specific C++ type.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class provides an efficient mapping between a given Interface type, and a particular implementat...
Utility class for implementing users of storage classes uniqued by a StorageUniquer.
static LogicalResult verifyInvariants(Args... args)
Default implementation that just returns success.
static void attachInterface(MLIRContext &context)
Attach the given models as implementations of the corresponding interfaces for the concrete storage u...
static bool classof(T val)
Provide an implementation of 'classof' that compares the type id of the provided value with that of t...
static ConcreteT get(MLIRContext *ctx, Args &&...args)
Get or create a new ConcreteT instance within the ctx.
LogicalResult mutate(Args &&...args)
Mutate the current storage instance.
static TypeID getTypeID()
Return a unique identifier for the concrete type.
static ConcreteT getFromOpaquePointer(const void *ptr)
Get an instance of the concrete type from a void pointer.
static HasTraitFn getHasTraitFn()
Returns the function that returns true if the given Trait ID matches the IDs of any of the traits def...
static ConcreteT getChecked(function_ref< InFlightDiagnostic()> emitErrorFn, MLIRContext *ctx, Args... args)
Get or create a new ConcreteT instance within the ctx.
bool(*)(TypeID) HasTraitFn
ImplType * getImpl() const
Utility for easy access to the storage instance.
static ConcreteT getChecked(const Location &loc, Args &&...args)
Get or create a new ConcreteT instance within the ctx, defined at the given, potentially unknown,...
static auto getWalkImmediateSubElementsFn()
Returns a function that walks immediate sub elements of a given instance of the storage user.
static detail::InterfaceMap getInterfaceMap()
Returns an interface map for the interfaces registered to this storage user.
static auto getReplaceImmediateSubElementsFn()
Returns a function that replaces immediate sub elements of a given instance of the storage user.
Helper class for implementing traits for storage classes.
ConcreteType getInstance() const
Return the derived instance.
bool hasTrait(TypeID traitID)
Returns true if this given Trait ID matches the IDs of any of the provided trait types Traits.
auto replaceImmediateSubElementsImpl(T derived, ArrayRef< Attribute > &replAttrs, ArrayRef< Type > &replTypes)
This function provides the underlying implementation for the SubElementInterface replace method,...
void walkImmediateSubElementsImpl(T derived, function_ref< void(Attribute)> walkAttrsFn, function_ref< void(Type)> walkTypesFn)
This function provides the underlying implementation for the SubElementInterface walk method,...
llvm::unique_function< InFlightDiagnostic()> getDefaultDiagnosticEmitFn(MLIRContext *ctx)
Utility method to generate a callback that can be used to generate a diagnostic when checking the con...
void handleAdditionOfUndefinedPromisedInterface(Dialect &dialect, TypeID interfaceRequestorID, TypeID interfaceID)
Checks if the given interface, which is attempting to be attached, is a promised interface of this di...
Include the generated interface declarations.
This trait is used to determine if a storage user, like Type, is mutable or not.