MLIR 22.0.0git
AttributeSupport.h
Go to the documentation of this file.
1//===- AttributeSupport.h ---------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines support types for registering dialect extended attributes.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef MLIR_IR_ATTRIBUTESUPPORT_H
14#define MLIR_IR_ATTRIBUTESUPPORT_H
15
16#include "mlir/IR/MLIRContext.h"
18#include "mlir/IR/Types.h"
19#include "llvm/ADT/PointerIntPair.h"
20#include "llvm/ADT/Twine.h"
21
22namespace mlir {
23//===----------------------------------------------------------------------===//
24// AbstractAttribute
25//===----------------------------------------------------------------------===//
26
27/// This class contains all of the static information common to all instances of
28/// a registered Attribute.
29class AbstractAttribute {
30public:
31 using HasTraitFn = llvm::unique_function<bool(TypeID) const>;
36
37 /// Look up the specified abstract attribute in the MLIRContext and return a
38 /// reference to it.
39 static const AbstractAttribute &lookup(TypeID typeID, MLIRContext *context);
40
41 /// Look up the specified abstract attribute in the MLIRContext and return a
42 /// reference to it if it exists.
43 static std::optional<std::reference_wrapper<const AbstractAttribute>>
44 lookup(StringRef name, MLIRContext *context);
45
46 /// This method is used by Dialect objects when they register the list of
47 /// attributes they contain.
48 template <typename T>
49 static AbstractAttribute get(Dialect &dialect) {
50 return AbstractAttribute(dialect, T::getInterfaceMap(), T::getHasTraitFn(),
51 T::getWalkImmediateSubElementsFn(),
52 T::getReplaceImmediateSubElementsFn(),
53 T::getTypeID(), T::name);
54 }
55
56 /// This method is used by Dialect objects to register attributes with
57 /// custom TypeIDs.
58 /// The use of this method is in general discouraged in favor of
59 /// 'get<CustomAttribute>(dialect)'.
61 get(Dialect &dialect, detail::InterfaceMap &&interfaceMap,
63 WalkImmediateSubElementsFn walkImmediateSubElementsFn,
64 ReplaceImmediateSubElementsFn replaceImmediateSubElementsFn,
65 TypeID typeID, StringRef name) {
66 return AbstractAttribute(dialect, std::move(interfaceMap),
67 std::move(hasTrait), walkImmediateSubElementsFn,
68 replaceImmediateSubElementsFn, typeID, name);
69 }
70
71 /// Return the dialect this attribute was registered to.
72 Dialect &getDialect() const { return const_cast<Dialect &>(dialect); }
73
74 /// Returns an instance of the concept object for the given interface if it
75 /// was registered to this attribute, null otherwise. This should not be used
76 /// directly.
77 template <typename T>
78 typename T::Concept *getInterface() const {
79 return interfaceMap.lookup<T>();
80 }
81
82 /// Returns true if the attribute has the interface with the given ID
83 /// registered.
84 bool hasInterface(TypeID interfaceID) const {
85 return interfaceMap.contains(interfaceID);
86 }
87
88 /// Returns true if the attribute has a particular trait.
89 template <template <typename T> class Trait>
90 bool hasTrait() const {
91 return hasTraitFn(TypeID::get<Trait>());
92 }
93
94 /// Returns true if the attribute has a particular trait.
95 bool hasTrait(TypeID traitID) const { return hasTraitFn(traitID); }
96
97 /// Walk the immediate sub-elements of this attribute.
99 function_ref<void(Attribute)> walkAttrsFn,
100 function_ref<void(Type)> walkTypesFn) const;
101
102 /// Replace the immediate sub-elements of this attribute.
104 ArrayRef<Attribute> replAttrs,
105 ArrayRef<Type> replTypes) const;
106
107 /// Return the unique identifier representing the concrete attribute class.
108 TypeID getTypeID() const { return typeID; }
109
110 /// Return the unique name representing the type.
111 StringRef getName() const { return name; }
112
113private:
114 AbstractAttribute(Dialect &dialect, detail::InterfaceMap &&interfaceMap,
115 HasTraitFn &&hasTraitFn,
116 WalkImmediateSubElementsFn walkImmediateSubElementsFn,
117 ReplaceImmediateSubElementsFn replaceImmediateSubElementsFn,
118 TypeID typeID, StringRef name)
119 : dialect(dialect), interfaceMap(std::move(interfaceMap)),
120 hasTraitFn(std::move(hasTraitFn)),
121 walkImmediateSubElementsFn(walkImmediateSubElementsFn),
122 replaceImmediateSubElementsFn(replaceImmediateSubElementsFn),
123 typeID(typeID), name(name) {}
124
125 /// Give StorageUserBase access to the mutable lookup.
126 template <typename ConcreteT, typename BaseT, typename StorageT,
127 typename UniquerT, template <typename T> class... Traits>
129
130 /// Look up the specified abstract attribute in the MLIRContext and return a
131 /// (mutable) pointer to it. Return a null pointer if the attribute could not
132 /// be found in the context.
133 static AbstractAttribute *lookupMutable(TypeID typeID, MLIRContext *context);
134
135 /// This is the dialect that this attribute was registered to.
136 const Dialect &dialect;
137
138 /// This is a collection of the interfaces registered to this attribute.
139 detail::InterfaceMap interfaceMap;
140
141 /// Function to check if the attribute has a particular trait.
142 HasTraitFn hasTraitFn;
143
144 /// Function to walk the immediate sub-elements of this attribute.
145 WalkImmediateSubElementsFn walkImmediateSubElementsFn;
146
147 /// Function to replace the immediate sub-elements of this attribute.
148 ReplaceImmediateSubElementsFn replaceImmediateSubElementsFn;
149
150 /// The unique identifier of the derived Attribute class.
151 const TypeID typeID;
152
153 /// The unique name of this attribute. The string is not owned by the context,
154 /// so the lifetime of this string should outlive the MLIR context.
155 const StringRef name;
156};
157
158//===----------------------------------------------------------------------===//
159// AttributeStorage
160//===----------------------------------------------------------------------===//
161
162namespace detail {
163class AttributeUniquer;
164class DistinctAttributeUniquer;
165} // namespace detail
166
167/// Base storage class appearing in an attribute. Derived storage classes should
168/// only be constructed within the context of the AttributeUniquer.
172 friend StorageUniquer;
173
174public:
175 /// Return the abstract descriptor for this attribute.
177 assert(abstractAttribute && "Malformed attribute storage object.");
178 return *abstractAttribute;
179 }
180
181protected:
182 /// Set the abstract attribute for this storage instance. This is used by the
183 /// AttributeUniquer when initializing a newly constructed storage object.
185 abstractAttribute = &abstractAttr;
186 }
187
188 /// Default initialization for attribute storage classes that require no
189 /// additional initialization.
190 void initialize(MLIRContext *context) {}
191
192private:
193 /// The abstract descriptor for this attribute.
194 const AbstractAttribute *abstractAttribute = nullptr;
195};
196
197/// Default storage type for attributes that require no additional
198/// initialization or storage.
200
201//===----------------------------------------------------------------------===//
202// AttributeStorageAllocator
203//===----------------------------------------------------------------------===//
204
205// This is a utility allocator used to allocate memory for instances of derived
206// Attributes.
208
209//===----------------------------------------------------------------------===//
210// AttributeUniquer
211//===----------------------------------------------------------------------===//
212namespace detail {
213// A utility class to get, or create, unique instances of attributes within an
214// MLIRContext. This class manages all creation and uniquing of attributes.
216public:
217 /// Get an uniqued instance of an attribute T.
218 template <typename T, typename... Args>
219 static T get(MLIRContext *ctx, Args &&...args) {
220 return getWithTypeID<T, Args...>(ctx, T::getTypeID(),
221 std::forward<Args>(args)...);
222 }
223
224 /// Get an uniqued instance of a parametric attribute T.
225 /// The use of this method is in general discouraged in favor of
226 /// 'get<T, Args>(ctx, args)'.
227 template <typename T, typename... Args>
228 static std::enable_if_t<
229 !std::is_same<typename T::ImplType, AttributeStorage>::value, T>
230 getWithTypeID(MLIRContext *ctx, TypeID typeID, Args &&...args) {
231#ifndef NDEBUG
233 llvm::report_fatal_error(
234 llvm::Twine("can't create Attribute '") + llvm::getTypeName<T>() +
235 "' because storage uniquer isn't initialized: the dialect was likely "
236 "not loaded, or the attribute wasn't added with addAttributes<...>() "
237 "in the Dialect::initialize() method.");
238#endif
239 return ctx->getAttributeUniquer().get<typename T::ImplType>(
240 [typeID, ctx](AttributeStorage *storage) {
241 initializeAttributeStorage(storage, ctx, typeID);
242
243 // Execute any additional attribute storage initialization with the
244 // context.
245 static_cast<typename T::ImplType *>(storage)->initialize(ctx);
246 },
247 typeID, std::forward<Args>(args)...);
248 }
249 /// Get an uniqued instance of a singleton attribute T.
250 /// The use of this method is in general discouraged in favor of
251 /// 'get<T, Args>(ctx, args)'.
252 template <typename T>
253 static std::enable_if_t<
254 std::is_same<typename T::ImplType, AttributeStorage>::value, T>
256#ifndef NDEBUG
258 llvm::report_fatal_error(
259 llvm::Twine("can't create Attribute '") + llvm::getTypeName<T>() +
260 "' because storage uniquer isn't initialized: the dialect was likely "
261 "not loaded, or the attribute wasn't added with addAttributes<...>() "
262 "in the Dialect::initialize() method.");
263#endif
264 return ctx->getAttributeUniquer().get<typename T::ImplType>(typeID);
265 }
266
267 template <typename T, typename... Args>
268 static LogicalResult mutate(MLIRContext *ctx, typename T::ImplType *impl,
269 Args &&...args) {
270 assert(impl && "cannot mutate null attribute");
271 return ctx->getAttributeUniquer().mutate(T::getTypeID(), impl,
272 std::forward<Args>(args)...);
273 }
274
275 /// Register an attribute instance T with the uniquer.
276 template <typename T>
277 static void registerAttribute(MLIRContext *ctx) {
278 registerAttribute<T>(ctx, T::getTypeID());
279 }
280
281 /// Register a parametric attribute instance T with the uniquer.
282 /// The use of this method is in general discouraged in favor of
283 /// 'registerAttribute<T>(ctx)'.
284 template <typename T>
285 static std::enable_if_t<
286 !std::is_same<typename T::ImplType, AttributeStorage>::value>
289 .registerParametricStorageType<typename T::ImplType>(typeID);
290 }
291 /// Register a singleton attribute instance T with the uniquer.
292 /// The use of this method is in general discouraged in favor of
293 /// 'registerAttribute<T>(ctx)'.
294 template <typename T>
295 static std::enable_if_t<
296 std::is_same<typename T::ImplType, AttributeStorage>::value>
299 .registerSingletonStorageType<typename T::ImplType>(
300 typeID, [ctx, typeID](AttributeStorage *storage) {
301 initializeAttributeStorage(storage, ctx, typeID);
302 });
303 }
304
305private:
306 /// Initialize the given attribute storage instance.
307 static void initializeAttributeStorage(AttributeStorage *storage,
308 MLIRContext *ctx, TypeID attrID);
309};
310
311// Internal function called by ODS generated code.
312// Default initializes the type within a FailureOr<T> if T is default
313// constructible and returns a reference to the instance.
314// Otherwise, returns a reference to the FailureOr<T>.
315template <class T>
316decltype(auto) unwrapForCustomParse(FailureOr<T> &failureOr) {
317 if constexpr (std::is_default_constructible_v<T>)
318 return failureOr.emplace();
319 else
320 return failureOr;
321}
322
323} // namespace detail
324
325} // namespace mlir
326
327#endif
LogicalResult initialize(unsigned origNumLoops, ArrayRef< ReassociationIndices > foldedIterationDims)
This class contains all of the static information common to all instances of a registered Attribute.
llvm::unique_function< bool(TypeID) const > HasTraitFn
function_ref< void( Attribute, function_ref< void(Attribute)>, function_ref< void(Type)>)> WalkImmediateSubElementsFn
static AbstractAttribute get(Dialect &dialect)
This method is used by Dialect objects when they register the list of attributes they contain.
function_ref< Attribute(Attribute, ArrayRef< Attribute >, ArrayRef< Type >)> ReplaceImmediateSubElementsFn
static const AbstractAttribute & lookup(TypeID typeID, MLIRContext *context)
Look up the specified abstract attribute in the MLIRContext and return a reference to it.
TypeID getTypeID() const
Return the unique identifier representing the concrete attribute class.
Dialect & getDialect() const
Return the dialect this attribute was registered to.
static AbstractAttribute get(Dialect &dialect, detail::InterfaceMap &&interfaceMap, HasTraitFn &&hasTrait, WalkImmediateSubElementsFn walkImmediateSubElementsFn, ReplaceImmediateSubElementsFn replaceImmediateSubElementsFn, TypeID typeID, StringRef name)
This method is used by Dialect objects to register attributes with custom TypeIDs.
bool hasTrait() const
Returns true if the attribute has a particular trait.
T::Concept * getInterface() const
Returns an instance of the concept object for the given interface if it was registered to this attrib...
void walkImmediateSubElements(Attribute attr, function_ref< void(Attribute)> walkAttrsFn, function_ref< void(Type)> walkTypesFn) const
Walk the immediate sub-elements of this attribute.
bool hasTrait(TypeID traitID) const
Returns true if the attribute has a particular trait.
Attribute replaceImmediateSubElements(Attribute attr, ArrayRef< Attribute > replAttrs, ArrayRef< Type > replTypes) const
Replace the immediate sub-elements of this attribute.
StringRef getName() const
Return the unique name representing the type.
bool hasInterface(TypeID interfaceID) const
Returns true if the attribute has the interface with the given ID registered.
Base storage class appearing in an attribute.
void initializeAbstractAttribute(const AbstractAttribute &abstractAttr)
Set the abstract attribute for this storage instance.
const AbstractAttribute & getAbstractAttribute() const
Return the abstract descriptor for this attribute.
void initialize(MLIRContext *context)
Default initialization for attribute storage classes that require no additional initialization.
Attributes are known-constant values of operations.
Definition Attributes.h:25
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition Dialect.h:38
MLIRContext is the top-level object for a collection of MLIR operations.
Definition MLIRContext.h:63
StorageUniquer & getAttributeUniquer()
Returns the storage uniquer used for constructing attribute storage instances.
This class acts as the base storage that all storage classes must derived from.
This is a utility allocator used to allocate memory for instances of derived types.
LogicalResult mutate(TypeID id, Storage *storage, Args &&...args)
Changes the mutable component of 'storage' by forwarding the trailing arguments to the 'mutate' funct...
void registerSingletonStorageType(TypeID id, function_ref< void(Storage *)> initFn)
Register a new singleton storage class, this is necessary to get the singletone instance.
Storage * get(function_ref< void(Storage *)> initFn, TypeID id, Args &&...args)
Gets a uniqued instance of 'Storage'.
bool isSingletonStorageInitialized(TypeID id)
Test if there is a singleton storage uniquer initialized for the provided TypeID.
bool isParametricStorageInitialized(TypeID id)
Test if there is a parametric storage uniquer initialized for the provided TypeID.
void registerParametricStorageType(TypeID id)
Register a new parametric storage class, this is necessary to create instances of this class type.
This class provides an efficient unique identifier for a specific C++ type.
Definition TypeID.h:107
static TypeID get()
Construct a type info object for the given type T.
Definition TypeID.h:245
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
static std::enable_if_t< std::is_same< typename T::ImplType, AttributeStorage >::value, T > getWithTypeID(MLIRContext *ctx, TypeID typeID)
Get an uniqued instance of a singleton attribute T.
static void registerAttribute(MLIRContext *ctx)
Register an attribute instance T with the uniquer.
static std::enable_if_t< !std::is_same< typename T::ImplType, AttributeStorage >::value > registerAttribute(MLIRContext *ctx, TypeID typeID)
Register a parametric attribute instance T with the uniquer.
static T get(MLIRContext *ctx, Args &&...args)
Get an uniqued instance of an attribute T.
static std::enable_if_t< !std::is_same< typename T::ImplType, AttributeStorage >::value, T > getWithTypeID(MLIRContext *ctx, TypeID typeID, Args &&...args)
Get an uniqued instance of a parametric attribute T.
static LogicalResult mutate(MLIRContext *ctx, typename T::ImplType *impl, Args &&...args)
static std::enable_if_t< std::is_same< typename T::ImplType, AttributeStorage >::value > registerAttribute(MLIRContext *ctx, TypeID typeID)
Register a singleton attribute instance T with the uniquer.
A specialized attribute uniquer for distinct attributes that always allocates since the distinct attr...
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.
AttrTypeReplacer.
decltype(auto) unwrapForCustomParse(FailureOr< T > &failureOr)
Include the generated interface declarations.
StorageUniquer::StorageAllocator AttributeStorageAllocator
llvm::function_ref< Fn > function_ref
Definition LLVM.h:152
AttributeStorage DefaultAttributeStorage
Default storage type for attributes that require no additional initialization or storage.