MLIR  16.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 
22 namespace mlir {
23 class MLIRContext;
24 class Type;
25 
26 //===----------------------------------------------------------------------===//
27 // AbstractAttribute
28 //===----------------------------------------------------------------------===//
29 
30 /// This class contains all of the static information common to all instances of
31 /// a registered Attribute.
33 public:
34  using HasTraitFn = llvm::unique_function<bool(TypeID) const>;
35 
36  /// Look up the specified abstract attribute in the MLIRContext and return a
37  /// reference to it.
38  static const AbstractAttribute &lookup(TypeID typeID, MLIRContext *context);
39 
40  /// This method is used by Dialect objects when they register the list of
41  /// attributes they contain.
42  template <typename T>
43  static AbstractAttribute get(Dialect &dialect) {
44  return AbstractAttribute(dialect, T::getInterfaceMap(), T::getHasTraitFn(),
45  T::getTypeID());
46  }
47 
48  /// This method is used by Dialect objects to register attributes with
49  /// custom TypeIDs.
50  /// The use of this method is in general discouraged in favor of
51  /// 'get<CustomAttribute>(dialect)'.
52  static AbstractAttribute get(Dialect &dialect,
53  detail::InterfaceMap &&interfaceMap,
54  HasTraitFn &&hasTrait, TypeID typeID) {
55  return AbstractAttribute(dialect, std::move(interfaceMap),
56  std::move(hasTrait), typeID);
57  }
58 
59  /// Return the dialect this attribute was registered to.
60  Dialect &getDialect() const { return const_cast<Dialect &>(dialect); }
61 
62  /// Returns an instance of the concept object for the given interface if it
63  /// was registered to this attribute, null otherwise. This should not be used
64  /// directly.
65  template <typename T>
66  typename T::Concept *getInterface() const {
67  return interfaceMap.lookup<T>();
68  }
69 
70  /// Returns true if the attribute has the interface with the given ID
71  /// registered.
72  bool hasInterface(TypeID interfaceID) const {
73  return interfaceMap.contains(interfaceID);
74  }
75 
76  /// Returns true if the attribute has a particular trait.
77  template <template <typename T> class Trait>
78  bool hasTrait() const {
79  return hasTraitFn(TypeID::get<Trait>());
80  }
81 
82  /// Returns true if the attribute has a particular trait.
83  bool hasTrait(TypeID traitID) const { return hasTraitFn(traitID); }
84 
85  /// Return the unique identifier representing the concrete attribute class.
86  TypeID getTypeID() const { return typeID; }
87 
88 private:
89  AbstractAttribute(Dialect &dialect, detail::InterfaceMap &&interfaceMap,
90  HasTraitFn &&hasTrait, TypeID typeID)
91  : dialect(dialect), interfaceMap(std::move(interfaceMap)),
92  hasTraitFn(std::move(hasTrait)), typeID(typeID) {}
93 
94  /// Give StorageUserBase access to the mutable lookup.
95  template <typename ConcreteT, typename BaseT, typename StorageT,
96  typename UniquerT, template <typename T> class... Traits>
98 
99  /// Look up the specified abstract attribute in the MLIRContext and return a
100  /// (mutable) pointer to it. Return a null pointer if the attribute could not
101  /// be found in the context.
102  static AbstractAttribute *lookupMutable(TypeID typeID, MLIRContext *context);
103 
104  /// This is the dialect that this attribute was registered to.
105  const Dialect &dialect;
106 
107  /// This is a collection of the interfaces registered to this attribute.
108  detail::InterfaceMap interfaceMap;
109 
110  /// Function to check if the attribute has a particular trait.
111  HasTraitFn hasTraitFn;
112 
113  /// The unique identifier of the derived Attribute class.
114  const TypeID typeID;
115 };
116 
117 //===----------------------------------------------------------------------===//
118 // AttributeStorage
119 //===----------------------------------------------------------------------===//
120 
121 namespace detail {
122 class AttributeUniquer;
123 } // namespace detail
124 
125 /// Base storage class appearing in an attribute. Derived storage classes should
126 /// only be constructed within the context of the AttributeUniquer.
129  friend StorageUniquer;
130 
131 public:
132  /// Return the abstract descriptor for this attribute.
134  assert(abstractAttribute && "Malformed attribute storage object.");
135  return *abstractAttribute;
136  }
137 
138 protected:
139  /// Set the abstract attribute for this storage instance. This is used by the
140  /// AttributeUniquer when initializing a newly constructed storage object.
141  void initializeAbstractAttribute(const AbstractAttribute &abstractAttr) {
142  abstractAttribute = &abstractAttr;
143  }
144 
145  /// Default initialization for attribute storage classes that require no
146  /// additional initialization.
147  void initialize(MLIRContext *context) {}
148 
149 private:
150  /// The abstract descriptor for this attribute.
151  const AbstractAttribute *abstractAttribute = nullptr;
152 };
153 
154 /// Default storage type for attributes that require no additional
155 /// initialization or storage.
157 
158 //===----------------------------------------------------------------------===//
159 // AttributeStorageAllocator
160 //===----------------------------------------------------------------------===//
161 
162 // This is a utility allocator used to allocate memory for instances of derived
163 // Attributes.
165 
166 //===----------------------------------------------------------------------===//
167 // AttributeUniquer
168 //===----------------------------------------------------------------------===//
169 namespace detail {
170 // A utility class to get, or create, unique instances of attributes within an
171 // MLIRContext. This class manages all creation and uniquing of attributes.
173 public:
174  /// Get an uniqued instance of an attribute T.
175  template <typename T, typename... Args>
176  static T get(MLIRContext *ctx, Args &&...args) {
177  return getWithTypeID<T, Args...>(ctx, T::getTypeID(),
178  std::forward<Args>(args)...);
179  }
180 
181  /// Get an uniqued instance of a parametric attribute T.
182  /// The use of this method is in general discouraged in favor of
183  /// 'get<T, Args>(ctx, args)'.
184  template <typename T, typename... Args>
185  static typename std::enable_if_t<
187  getWithTypeID(MLIRContext *ctx, TypeID typeID, Args &&...args) {
188 #ifndef NDEBUG
190  llvm::report_fatal_error(
191  llvm::Twine("can't create Attribute '") + llvm::getTypeName<T>() +
192  "' because storage uniquer isn't initialized: the dialect was likely "
193  "not loaded, or the attribute wasn't added with addAttributes<...>() "
194  "in the Dialect::initialize() method.");
195 #endif
196  return ctx->getAttributeUniquer().get<typename T::ImplType>(
197  [typeID, ctx](AttributeStorage *storage) {
198  initializeAttributeStorage(storage, ctx, typeID);
199 
200  // Execute any additional attribute storage initialization with the
201  // context.
202  static_cast<typename T::ImplType *>(storage)->initialize(ctx);
203  },
204  typeID, std::forward<Args>(args)...);
205  }
206  /// Get an uniqued instance of a singleton attribute T.
207  /// The use of this method is in general discouraged in favor of
208  /// 'get<T, Args>(ctx, args)'.
209  template <typename T>
210  static typename std::enable_if_t<
213 #ifndef NDEBUG
215  llvm::report_fatal_error(
216  llvm::Twine("can't create Attribute '") + llvm::getTypeName<T>() +
217  "' because storage uniquer isn't initialized: the dialect was likely "
218  "not loaded, or the attribute wasn't added with addAttributes<...>() "
219  "in the Dialect::initialize() method.");
220 #endif
221  return ctx->getAttributeUniquer().get<typename T::ImplType>(typeID);
222  }
223 
224  template <typename T, typename... Args>
225  static LogicalResult mutate(MLIRContext *ctx, typename T::ImplType *impl,
226  Args &&...args) {
227  assert(impl && "cannot mutate null attribute");
228  return ctx->getAttributeUniquer().mutate(T::getTypeID(), impl,
229  std::forward<Args>(args)...);
230  }
231 
232  /// Register an attribute instance T with the uniquer.
233  template <typename T>
234  static void registerAttribute(MLIRContext *ctx) {
235  registerAttribute<T>(ctx, T::getTypeID());
236  }
237 
238  /// Register a parametric attribute instance T with the uniquer.
239  /// The use of this method is in general discouraged in favor of
240  /// 'registerAttribute<T>(ctx)'.
241  template <typename T>
242  static typename std::enable_if_t<
243  !std::is_same<typename T::ImplType, AttributeStorage>::value>
245  ctx->getAttributeUniquer()
246  .registerParametricStorageType<typename T::ImplType>(typeID);
247  }
248  /// Register a singleton attribute instance T with the uniquer.
249  /// The use of this method is in general discouraged in favor of
250  /// 'registerAttribute<T>(ctx)'.
251  template <typename T>
252  static typename std::enable_if_t<
253  std::is_same<typename T::ImplType, AttributeStorage>::value>
255  ctx->getAttributeUniquer()
256  .registerSingletonStorageType<typename T::ImplType>(
257  typeID, [ctx, typeID](AttributeStorage *storage) {
258  initializeAttributeStorage(storage, ctx, typeID);
259  });
260  }
261 
262 private:
263  /// Initialize the given attribute storage instance.
264  static void initializeAttributeStorage(AttributeStorage *storage,
265  MLIRContext *ctx, TypeID attrID);
266 };
267 } // namespace detail
268 
269 } // namespace mlir
270 
271 #endif
Include the generated interface declarations.
TypeID getTypeID() const
Return the unique identifier representing the concrete attribute class.
Storage * get(function_ref< void(Storage *)> initFn, TypeID id, Args &&...args)
Gets a uniqued instance of &#39;Storage&#39;.
llvm::unique_function< bool(TypeID) const > HasTraitFn
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.
T::Concept * getInterface() const
Returns an instance of the concept object for the given interface if it was registered to this attrib...
This is a utility allocator used to allocate memory for instances of derived types.
static const AbstractAttribute & lookup(TypeID typeID, MLIRContext *context)
Look up the specified abstract attribute in the MLIRContext and return a reference to it...
Dialect & getDialect() const
Return the dialect this attribute was registered to.
An inlay hint that for a type annotation.
static constexpr const bool value
bool hasTrait() const
Returns true if the attribute has a particular trait.
This class provides an efficient unique identifier for a specific C++ type.
Definition: TypeID.h:104
static void registerAttribute(MLIRContext *ctx)
Register an attribute instance T with the uniquer.
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26
bool isSingletonStorageInitialized(TypeID id)
Test if there is a singleton storage uniquer initialized for the provided TypeID. ...
This class provides an efficient mapping between a given Interface type, and a particular implementat...
static LogicalResult mutate(MLIRContext *ctx, typename T::ImplType *impl, Args &&...args)
void registerParametricStorageType(TypeID id)
Register a new parametric storage class, this is necessary to create instances of this class type...
LogicalResult mutate(TypeID id, Storage *storage, Args &&...args)
Changes the mutable component of &#39;storage&#39; by forwarding the trailing arguments to the &#39;mutate&#39; funct...
bool isParametricStorageInitialized(TypeID id)
Test if there is a parametric storage uniquer initialized for the provided TypeID.
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.
StorageUniquer & getAttributeUniquer()
Returns the storage uniquer used for constructing attribute storage instances.
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:41
void initialize(MLIRContext *context)
Default initialization for attribute storage classes that require no additional initialization.
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.
A utility class to get or create instances of "storage classes".
This class acts as the base storage that all storage classes must derived from.
bool hasTrait(TypeID traitID) const
Returns true if the attribute has a particular trait.
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.
Utility class for implementing users of storage classes uniqued by a StorageUniquer.
const AbstractAttribute & getAbstractAttribute() const
Return the abstract descriptor for this attribute.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:55
void initializeAbstractAttribute(const AbstractAttribute &abstractAttr)
Set the abstract attribute for this storage instance.
Base storage class appearing in an attribute.
bool hasInterface(TypeID interfaceID) const
Returns true if the attribute has the interface with the given ID registered.
This class contains all of the static information common to all instances of a registered Attribute...
void registerSingletonStorageType(TypeID id, function_ref< void(Storage *)> initFn)
Register a new singleton storage class, this is necessary to get the singletone instance.