MLIR 22.0.0git
Attributes.h
Go to the documentation of this file.
1//===- Attributes.h - MLIR Attribute Classes --------------------*- 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#ifndef MLIR_IR_ATTRIBUTES_H
10#define MLIR_IR_ATTRIBUTES_H
11
13#include "llvm/Support/PointerLikeTypeTraits.h"
14
15namespace mlir {
16class AsmState;
17class StringAttr;
18
19/// Attributes are known-constant values of operations.
20///
21/// Instances of the Attribute class are references to immortal key-value pairs
22/// with immutable, uniqued keys owned by MLIRContext. As such, an Attribute is
23/// a thin wrapper around an underlying storage pointer. Attributes are usually
24/// passed by value.
25class Attribute {
26public:
27 /// Utility class for implementing attributes.
28 template <typename ConcreteType, typename BaseType, typename StorageType,
29 template <typename T> class... Traits>
30 using AttrBase = detail::StorageUserBase<ConcreteType, BaseType, StorageType,
31 detail::AttributeUniquer, Traits...>;
32
34 using ValueType = void;
36
37 constexpr Attribute() = default;
38 /* implicit */ Attribute(const ImplType *impl)
39 : impl(const_cast<ImplType *>(impl)) {}
40
41 Attribute(const Attribute &other) = default;
42 Attribute &operator=(const Attribute &other) = default;
43
44 bool operator==(Attribute other) const { return impl == other.impl; }
45 bool operator!=(Attribute other) const { return !(*this == other); }
46 explicit operator bool() const { return impl; }
47
48 bool operator!() const { return impl == nullptr; }
49
50 /// Return a unique identifier for the concrete attribute type. This is used
51 /// to support dynamic type casting.
52 TypeID getTypeID() { return impl->getAbstractAttribute().getTypeID(); }
53
54 /// Return the context this attribute belongs to.
55 MLIRContext *getContext() const;
56
57 /// Get the dialect this attribute is registered to.
59 return impl->getAbstractAttribute().getDialect();
60 }
61
62 /// Print the attribute. If `elideType` is set, the attribute is printed
63 /// without a trailing colon type if it has one.
64 void print(raw_ostream &os, bool elideType = false) const;
65 void print(raw_ostream &os, AsmState &state, bool elideType = false) const;
66 void dump() const;
67
68 /// Print the attribute without dialect wrapping.
69 void printStripped(raw_ostream &os) const;
70 void printStripped(raw_ostream &os, AsmState &state) const;
71
72 /// Get an opaque pointer to the attribute.
73 const void *getAsOpaquePointer() const { return impl; }
74 /// Construct an attribute from the opaque pointer representation.
75 static Attribute getFromOpaquePointer(const void *ptr) {
76 return Attribute(reinterpret_cast<const ImplType *>(ptr));
77 }
78
79 friend ::llvm::hash_code hash_value(Attribute arg);
80
81 /// Returns true if `InterfaceT` has been promised by the dialect or
82 /// implemented.
83 template <typename InterfaceT>
86 getDialect(), getTypeID(), InterfaceT::getInterfaceID()) ||
87 mlir::isa<InterfaceT>(*this);
88 }
89
90 /// Returns true if the type was registered with a particular trait.
91 template <template <typename T> class Trait>
92 bool hasTrait() {
93 return getAbstractAttribute().hasTrait<Trait>();
94 }
95
96 /// Return the abstract descriptor for this attribute.
98 return impl->getAbstractAttribute();
99 }
100
101 /// Walk all of the immediately nested sub-attributes and sub-types. This
102 /// method does not recurse into sub elements.
104 function_ref<void(Type)> walkTypesFn) const {
106 walkTypesFn);
107 }
108
109 /// Replace the immediately nested sub-attributes and sub-types with those
110 /// provided. The order of the provided elements is derived from the order of
111 /// the elements returned by the callbacks of `walkImmediateSubElements`. The
112 /// element at index 0 would replace the very first attribute given by
113 /// `walkImmediateSubElements`. On success, the new instance with the values
114 /// replaced is returned. If replacement fails, nullptr is returned.
116 ArrayRef<Type> replTypes) const {
117 return getAbstractAttribute().replaceImmediateSubElements(*this, replAttrs,
118 replTypes);
119 }
120
121 /// Walk this attribute and all attibutes/types nested within using the
122 /// provided walk functions. See `AttrTypeWalker` for information on the
123 /// supported walk function types.
124 template <WalkOrder Order = WalkOrder::PostOrder, typename... WalkFns>
125 auto walk(WalkFns &&...walkFns) {
126 AttrTypeWalker walker;
127 (walker.addWalk(std::forward<WalkFns>(walkFns)), ...);
128 return walker.walk<Order>(*this);
129 }
130
131 /// Recursively replace all of the nested sub-attributes and sub-types using
132 /// the provided map functions. Returns nullptr in the case of failure. See
133 /// `AttrTypeReplacer` for information on the support replacement function
134 /// types.
135 template <typename... ReplacementFns>
136 auto replace(ReplacementFns &&...replacementFns) {
137 AttrTypeReplacer replacer;
138 (replacer.addReplacement(std::forward<ReplacementFns>(replacementFns)),
139 ...);
140 return replacer.replace(*this);
141 }
142
143 /// Return the internal Attribute implementation.
144 ImplType *getImpl() const { return impl; }
145
146protected:
147 ImplType *impl{nullptr};
148};
149
151 attr.print(os);
152 return os;
153}
154
155inline ::llvm::hash_code hash_value(Attribute arg) {
157}
158
159//===----------------------------------------------------------------------===//
160// NamedAttribute
161//===----------------------------------------------------------------------===//
162
163/// NamedAttribute represents a combination of a name and an Attribute value.
165public:
166 NamedAttribute(StringAttr name, Attribute value);
167 NamedAttribute(StringRef name, Attribute value);
168
169 /// Return the name of the attribute.
170 StringAttr getName() const;
171
172 /// Return the dialect of the name of this attribute, if the name is prefixed
173 /// by a dialect namespace. For example, `llvm.fast_math` would return the
174 /// LLVM dialect (if it is loaded). Returns nullptr if the dialect isn't
175 /// loaded, or if the name is not prefixed by a dialect namespace.
176 Dialect *getNameDialect() const;
177
178 /// Return the value of the attribute.
179 Attribute getValue() const { return value; }
180
181 /// Set the name of this attribute.
182 void setName(StringAttr newName);
183
184 /// Set the value of this attribute.
185 void setValue(Attribute newValue) {
186 assert(value && "expected valid attribute value");
187 value = newValue;
188 }
189
190 /// Compare this attribute to the provided attribute, ordering by name.
191 bool operator<(const NamedAttribute &rhs) const;
192 /// Compare this attribute to the provided string, ordering by name.
193 bool operator<(StringRef rhs) const;
194
195 bool operator==(const NamedAttribute &rhs) const {
196 return name == rhs.name && value == rhs.value;
197 }
198 bool operator!=(const NamedAttribute &rhs) const { return !(*this == rhs); }
199
200private:
201 NamedAttribute(Attribute name, Attribute value) : name(name), value(value) {}
202
203 /// Allow access to internals to enable hashing.
204 friend ::llvm::hash_code hash_value(const NamedAttribute &arg);
205 friend DenseMapInfo<NamedAttribute>;
206
207 /// The name of the attribute. This is represented as a StringAttr, but
208 /// type-erased to Attribute in the field.
209 Attribute name;
210 /// The value of the attribute.
211 Attribute value;
212};
213
214inline ::llvm::hash_code hash_value(const NamedAttribute &arg) {
215 using AttrPairT = std::pair<Attribute, Attribute>;
216 return DenseMapInfo<AttrPairT>::getHashValue(AttrPairT(arg.name, arg.value));
217}
218
219/// Allow walking and replacing the subelements of a NamedAttribute.
220template <>
222 template <typename T>
223 static void walk(T param, AttrTypeImmediateSubElementWalker &walker) {
224 walker.walk(param.getName());
225 walker.walk(param.getValue());
226 }
227 template <typename T>
228 static T replace(T param, AttrSubElementReplacements &attrRepls,
229 TypeSubElementReplacements &typeRepls) {
230 ArrayRef<Attribute> paramRepls = attrRepls.take_front(2);
231 return T(cast<decltype(param.getName())>(paramRepls[0]), paramRepls[1]);
232 }
233};
234
235//===----------------------------------------------------------------------===//
236// AttributeTraitBase
237//===----------------------------------------------------------------------===//
238
239namespace AttributeTrait {
240/// This class represents the base of an attribute trait.
241template <typename ConcreteType, template <typename> class TraitType>
243} // namespace AttributeTrait
244
245//===----------------------------------------------------------------------===//
246// AttributeInterface
247//===----------------------------------------------------------------------===//
248
249/// This class represents the base of an attribute interface. See the definition
250/// of `detail::Interface` for requirements on the `Traits` type.
251template <typename ConcreteType, typename Traits>
253 : public detail::Interface<ConcreteType, Attribute, Traits, Attribute,
254 AttributeTrait::TraitBase> {
255public:
257 using InterfaceBase = detail::Interface<ConcreteType, Attribute, Traits,
260
261protected:
262 /// Returns the impl interface instance for the given type.
264#ifndef NDEBUG
265 // Check that the current interface isn't an unresolved promise for the
266 // given attribute.
268 attr.getDialect(), attr.getTypeID(), ConcreteType::getInterfaceID(),
269 llvm::getTypeName<ConcreteType>());
270#endif
271
272 return attr.getAbstractAttribute().getInterface<ConcreteType>();
273 }
274
275 /// Allow access to 'getInterfaceFor'.
277};
278
279//===----------------------------------------------------------------------===//
280// Core AttributeTrait
281//===----------------------------------------------------------------------===//
282
283namespace AttributeTrait {
284/// This trait is used to determine if an attribute is mutable or not. It is
285/// attached on an attribute if the corresponding ConcreteType defines a
286/// `mutate` function with proper signature.
287template <typename ConcreteType>
289
290/// This trait is used to determine if an attribute is a location or not. It is
291/// attached to an attribute by the user if they intend the attribute to be used
292/// as a location.
293template <typename ConcreteType>
294struct IsLocation : public AttributeTrait::TraitBase<ConcreteType, IsLocation> {
295};
296} // namespace AttributeTrait
297
298} // namespace mlir.
299
300namespace llvm {
301
302// Attribute hash just like pointers.
303template <>
304struct DenseMapInfo<mlir::Attribute> {
307 return mlir::Attribute(static_cast<mlir::Attribute::ImplType *>(pointer));
308 }
311 return mlir::Attribute(static_cast<mlir::Attribute::ImplType *>(pointer));
312 }
313 static unsigned getHashValue(mlir::Attribute val) {
314 return mlir::hash_value(val);
315 }
317 return LHS == RHS;
318 }
319};
320template <typename T>
322 T, std::enable_if_t<std::is_base_of<mlir::Attribute, T>::value &&
323 !mlir::detail::IsInterface<T>::value>>
324 : public DenseMapInfo<mlir::Attribute> {
325 static T getEmptyKey() {
326 const void *pointer = llvm::DenseMapInfo<const void *>::getEmptyKey();
327 return T::getFromOpaquePointer(pointer);
328 }
329 static T getTombstoneKey() {
331 return T::getFromOpaquePointer(pointer);
332 }
333};
334
335/// Allow LLVM to steal the low bits of Attributes.
336template <>
337struct PointerLikeTypeTraits<mlir::Attribute> {
338 static inline void *getAsVoidPointer(mlir::Attribute attr) {
339 return const_cast<void *>(attr.getAsOpaquePointer());
340 }
341 static inline mlir::Attribute getFromVoidPointer(void *ptr) {
343 }
344 static constexpr int NumLowBitsAvailable = llvm::PointerLikeTypeTraits<
346};
347
348template <>
349struct DenseMapInfo<mlir::NamedAttribute> {
352 return mlir::NamedAttribute(emptyAttr, emptyAttr);
353 }
356 return mlir::NamedAttribute(tombAttr, tombAttr);
357 }
358 static unsigned getHashValue(mlir::NamedAttribute val) {
359 return mlir::hash_value(val);
360 }
362 return lhs == rhs;
363 }
364};
365
366/// Add support for llvm style casts. We provide a cast between To and From if
367/// From is mlir::Attribute or derives from it.
368template <typename To, typename From>
369struct CastInfo<To, From,
370 std::enable_if_t<std::is_same_v<mlir::Attribute,
371 std::remove_const_t<From>> ||
372 std::is_base_of_v<mlir::Attribute, From>>>
374 DefaultDoCastIfPossible<To, From, CastInfo<To, From>> {
375 /// Arguments are taken as mlir::Attribute here and not as `From`, because
376 /// when casting from an intermediate type of the hierarchy to one of its
377 /// children, the val.getTypeID() inside T::classof will use the static
378 /// getTypeID of the parent instead of the non-static Type::getTypeID that
379 /// returns the dynamic ID. This means that T::classof would end up comparing
380 /// the static TypeID of the children to the static TypeID of its parent,
381 /// making it impossible to downcast from the parent to the child.
382 static inline bool isPossible(mlir::Attribute ty) {
383 /// Return a constant true instead of a dynamic true when casting to self or
384 /// up the hierarchy.
385 if constexpr (std::is_base_of_v<To, From>) {
386 return true;
387 } else {
388 return To::classof(ty);
389 }
390 }
391 static inline To doCast(mlir::Attribute attr) { return To(attr.getImpl()); }
392};
393
394} // namespace llvm
395
396#endif
lhs
This class contains all of the static information common to all instances of a registered Attribute.
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.
Attribute replaceImmediateSubElements(Attribute attr, ArrayRef< Attribute > replAttrs, ArrayRef< Type > replTypes) const
Replace the immediate sub-elements of this attribute.
This class provides management for the lifetime of the state used when printing the IR.
Definition AsmState.h:542
void walk(Attribute element)
Walk an attribute.
This is an attribute/type replacer that is naively cached.
Attribute replace(Attribute attr)
ArrayRef< T > take_front(unsigned n)
Take the first N replacements as an ArrayRef, dropping them from this replacement list.
void addWalk(WalkFn< Attribute > &&fn)
Register a walk function for a given attribute or type.
WalkResult walk(T element)
Walk the given attribute/type, and recursively walk any sub elements.
This class represents the base of an attribute interface.
Definition Attributes.h:254
detail::Interface< ConcreteType, Attribute, Traits, Attribute, AttributeTrait::TraitBase > InterfaceBase
Definition Attributes.h:257
AttributeInterface< ConcreteType, Traits > Base
Definition Attributes.h:256
static InterfaceBase::Concept * getInterfaceFor(Attribute attr)
Returns the impl interface instance for the given type.
Definition Attributes.h:263
Base storage class appearing in an attribute.
Attributes are known-constant values of operations.
Definition Attributes.h:25
detail::StorageUserBase< ConcreteType, BaseType, StorageType, detail::AttributeUniquer, Traits... > AttrBase
Utility class for implementing attributes.
Definition Attributes.h:30
Dialect & getDialect() const
Get the dialect this attribute is registered to.
Definition Attributes.h:58
friend::llvm::hash_code hash_value(Attribute arg)
AbstractAttribute AbstractTy
Definition Attributes.h:35
auto walk(WalkFns &&...walkFns)
Walk this attribute and all attibutes/types nested within using the provided walk functions.
Definition Attributes.h:125
ImplType * impl
Definition Attributes.h:147
bool operator!() const
Definition Attributes.h:48
const void * getAsOpaquePointer() const
Get an opaque pointer to the attribute.
Definition Attributes.h:73
Attribute(const ImplType *impl)
Definition Attributes.h:38
constexpr Attribute()=default
ImplType * getImpl() const
Return the internal Attribute implementation.
Definition Attributes.h:144
void printStripped(raw_ostream &os) const
Print the attribute without dialect wrapping.
bool operator==(Attribute other) const
Definition Attributes.h:44
void print(raw_ostream &os, bool elideType=false) const
Print the attribute.
auto replace(ReplacementFns &&...replacementFns)
Recursively replace all of the nested sub-attributes and sub-types using the provided map functions.
Definition Attributes.h:136
void walkImmediateSubElements(function_ref< void(Attribute)> walkAttrsFn, function_ref< void(Type)> walkTypesFn) const
Walk all of the immediately nested sub-attributes and sub-types.
Definition Attributes.h:103
void dump() const
bool operator!=(Attribute other) const
Definition Attributes.h:45
Attribute & operator=(const Attribute &other)=default
MLIRContext * getContext() const
Return the context this attribute belongs to.
auto replaceImmediateSubElements(ArrayRef< Attribute > replAttrs, ArrayRef< Type > replTypes) const
Replace the immediately nested sub-attributes and sub-types with those provided.
Definition Attributes.h:115
AttributeStorage ImplType
Definition Attributes.h:33
const AbstractTy & getAbstractAttribute() const
Return the abstract descriptor for this attribute.
Definition Attributes.h:97
bool hasTrait()
Returns true if the type was registered with a particular trait.
Definition Attributes.h:92
Attribute(const Attribute &other)=default
bool hasPromiseOrImplementsInterface()
Returns true if InterfaceT has been promised by the dialect or implemented.
Definition Attributes.h:84
TypeID getTypeID()
Return a unique identifier for the concrete attribute type.
Definition Attributes.h:52
static Attribute getFromOpaquePointer(const void *ptr)
Construct an attribute from the opaque pointer representation.
Definition Attributes.h:75
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
NamedAttribute represents a combination of a name and an Attribute value.
Definition Attributes.h:164
StringAttr getName() const
Return the name of the attribute.
void setName(StringAttr newName)
Set the name of this attribute.
bool operator==(const NamedAttribute &rhs) const
Definition Attributes.h:195
bool operator<(const NamedAttribute &rhs) const
Compare this attribute to the provided attribute, ordering by name.
NamedAttribute(StringAttr name, Attribute value)
Dialect * getNameDialect() const
Return the dialect of the name of this attribute, if the name is prefixed by a dialect namespace.
void setValue(Attribute newValue)
Set the value of this attribute.
Definition Attributes.h:185
Attribute getValue() const
Return the value of the attribute.
Definition Attributes.h:179
bool operator!=(const NamedAttribute &rhs) const
Definition Attributes.h:198
This class provides an efficient unique identifier for a specific C++ type.
Definition TypeID.h:107
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition Types.h:74
void addReplacement(ReplaceFn< Attribute > fn)
AttrTypeReplacerBase.
This class represents an abstract interface.
Interface< ConcreteType, Attribute, Traits, Attribute, AttributeTrait::TraitBase > InterfaceBase
Utility class for implementing users of storage classes uniqued by a StorageUniquer.
Helper class for implementing traits for storage classes.
The OpAsmOpInterface, see OpAsmInterface.td for more details.
Definition CallGraph.h:229
This trait is used to determine if an attribute is a dynamic attribute or not; it should only be impl...
Definition Attributes.h:239
detail::StorageUserTrait::IsMutable< ConcreteType > IsMutable
This trait is used to determine if an attribute is mutable or not.
Definition Attributes.h:288
detail::StorageUserTraitBase< ConcreteType, TraitType > TraitBase
This class represents the base of an attribute trait.
Definition Attributes.h:242
bool hasPromisedInterface(Dialect &dialect, TypeID interfaceRequestorID, TypeID interfaceID)
Checks if a promise has been made for the interface/requestor pair.
Definition Dialect.cpp:163
void handleUseOfUndefinedPromisedInterface(Dialect &dialect, TypeID interfaceRequestorID, TypeID interfaceID, StringRef interfaceName)
Checks if the given interface, which is attempting to be used, is a promised interface of this dialec...
Definition Dialect.cpp:150
Include the generated interface declarations.
llvm::DenseMapInfo< T, Enable > DenseMapInfo
Definition LLVM.h:122
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
WalkOrder
Traversal order for region, block and operation walk utilities.
Definition Visitors.h:28
AttrTypeSubElementReplacements< Attribute > AttrSubElementReplacements
inline ::llvm::hash_code hash_value(AffineExpr arg)
Make AffineExpr hashable.
Definition AffineExpr.h:247
llvm::function_ref< Fn > function_ref
Definition LLVM.h:152
AttrTypeSubElementReplacements< Type > TypeSubElementReplacements
static bool isPossible(mlir::Attribute ty)
Arguments are taken as mlir::Attribute here and not as From, because when casting from an intermediat...
Definition Attributes.h:382
static bool isEqual(mlir::Attribute LHS, mlir::Attribute RHS)
Definition Attributes.h:316
static unsigned getHashValue(mlir::Attribute val)
Definition Attributes.h:313
static mlir::Attribute getEmptyKey()
Definition Attributes.h:305
static mlir::Attribute getTombstoneKey()
Definition Attributes.h:309
static unsigned getHashValue(mlir::NamedAttribute val)
Definition Attributes.h:358
static mlir::NamedAttribute getEmptyKey()
Definition Attributes.h:350
static mlir::NamedAttribute getTombstoneKey()
Definition Attributes.h:354
static bool isEqual(mlir::NamedAttribute lhs, mlir::NamedAttribute rhs)
Definition Attributes.h:361
static void * getAsVoidPointer(mlir::Attribute attr)
Definition Attributes.h:338
static mlir::Attribute getFromVoidPointer(void *ptr)
Definition Attributes.h:341
static void walk(T param, AttrTypeImmediateSubElementWalker &walker)
Definition Attributes.h:223
static T replace(T param, AttrSubElementReplacements &attrRepls, TypeSubElementReplacements &typeRepls)
Definition Attributes.h:228
This class provides support for interacting with the SubElementInterfaces for different types of para...
This trait is used to determine if an attribute is a location or not.
Definition Attributes.h:294
This trait is used to determine if a storage user, like Type, is mutable or not.