MLIR 24.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#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
67 LLVM_DUMP_METHOD void dump() const;
68#endif
69
70 /// Print the attribute without dialect wrapping.
71 void printStripped(raw_ostream &os) const;
72 void printStripped(raw_ostream &os, AsmState &state) const;
73
74 /// Get an opaque pointer to the attribute.
75 const void *getAsOpaquePointer() const { return impl; }
76 /// Construct an attribute from the opaque pointer representation.
77 static Attribute getFromOpaquePointer(const void *ptr) {
78 return Attribute(reinterpret_cast<const ImplType *>(ptr));
79 }
80
81 friend ::llvm::hash_code hash_value(Attribute arg);
82
83 /// Returns true if `InterfaceT` has been promised by the dialect or
84 /// implemented.
85 template <typename InterfaceT>
88 getDialect(), getTypeID(), InterfaceT::getInterfaceID()) ||
89 mlir::isa<InterfaceT>(*this);
90 }
91
92 /// Returns true if the type was registered with a particular trait.
93 template <template <typename T> class Trait>
94 bool hasTrait() {
95 return getAbstractAttribute().hasTrait<Trait>();
96 }
97
98 /// Return the abstract descriptor for this attribute.
100 return impl->getAbstractAttribute();
101 }
102
103 /// Walk all of the immediately nested sub-attributes and sub-types. This
104 /// method does not recurse into sub elements.
106 function_ref<void(Type)> walkTypesFn) const {
108 walkTypesFn);
109 }
110
111 /// Replace the immediately nested sub-attributes and sub-types with those
112 /// provided. The order of the provided elements is derived from the order of
113 /// the elements returned by the callbacks of `walkImmediateSubElements`. The
114 /// element at index 0 would replace the very first attribute given by
115 /// `walkImmediateSubElements`. On success, the new instance with the values
116 /// replaced is returned. If replacement fails, nullptr is returned.
118 ArrayRef<Type> replTypes) const {
119 return getAbstractAttribute().replaceImmediateSubElements(*this, replAttrs,
120 replTypes);
121 }
122
123 /// Walk this attribute and all attibutes/types nested within using the
124 /// provided walk functions. See `AttrTypeWalker` for information on the
125 /// supported walk function types.
126 template <WalkOrder Order = WalkOrder::PostOrder, typename... WalkFns>
127 auto walk(WalkFns &&...walkFns) {
128 AttrTypeWalker walker;
129 (walker.addWalk(std::forward<WalkFns>(walkFns)), ...);
130 return walker.walk<Order>(*this);
131 }
132
133 /// Recursively replace all of the nested sub-attributes and sub-types using
134 /// the provided map functions. Returns nullptr in the case of failure. See
135 /// `AttrTypeReplacer` for information on the support replacement function
136 /// types.
137 template <typename... ReplacementFns>
138 auto replace(ReplacementFns &&...replacementFns) {
139 AttrTypeReplacer replacer;
140 (replacer.addReplacement(std::forward<ReplacementFns>(replacementFns)),
141 ...);
142 return replacer.replace(*this);
143 }
144
145 /// Return the internal Attribute implementation.
146 ImplType *getImpl() const { return impl; }
147
148protected:
149 ImplType *impl{nullptr};
150};
151
153 attr.print(os);
154 return os;
155}
156
157inline ::llvm::hash_code hash_value(Attribute arg) {
159}
160
161//===----------------------------------------------------------------------===//
162// NamedAttribute
163//===----------------------------------------------------------------------===//
164
165/// NamedAttribute represents a combination of a name and an Attribute value.
167public:
168 NamedAttribute(StringAttr name, Attribute value);
169 NamedAttribute(StringRef name, Attribute value);
170
171 /// Return the name of the attribute.
172 StringAttr getName() const;
173
174 /// Return the dialect of the name of this attribute, if the name is prefixed
175 /// by a dialect namespace. For example, `llvm.fast_math` would return the
176 /// LLVM dialect (if it is loaded). Returns nullptr if the dialect isn't
177 /// loaded, or if the name is not prefixed by a dialect namespace.
178 Dialect *getNameDialect() const;
179
180 /// Return the value of the attribute.
181 Attribute getValue() const { return value; }
182
183 /// Set the name of this attribute.
184 void setName(StringAttr newName);
185
186 /// Set the value of this attribute.
187 void setValue(Attribute newValue) {
188 assert(value && "expected valid attribute value");
189 value = newValue;
190 }
191
192 /// Compare this attribute to the provided attribute, ordering by name.
193 bool operator<(const NamedAttribute &rhs) const;
194 /// Compare this attribute to the provided string, ordering by name.
195 bool operator<(StringRef rhs) const;
196
197 bool operator==(const NamedAttribute &rhs) const {
198 return name == rhs.name && value == rhs.value;
199 }
200 bool operator!=(const NamedAttribute &rhs) const { return !(*this == rhs); }
201
202private:
203 NamedAttribute(Attribute name, Attribute value) : name(name), value(value) {}
204
205 /// Allow access to internals to enable hashing.
206 friend ::llvm::hash_code hash_value(const NamedAttribute &arg);
207 friend DenseMapInfo<NamedAttribute>;
208
209 /// The name of the attribute. This is represented as a StringAttr, but
210 /// type-erased to Attribute in the field.
211 Attribute name;
212 /// The value of the attribute.
213 Attribute value;
214};
215
216inline ::llvm::hash_code hash_value(const NamedAttribute &arg) {
217 using AttrPairT = std::pair<Attribute, Attribute>;
218 return DenseMapInfo<AttrPairT>::getHashValue(AttrPairT(arg.name, arg.value));
219}
220
221/// Allow walking and replacing the subelements of a NamedAttribute.
222template <>
224 template <typename T>
225 static void walk(T param, AttrTypeImmediateSubElementWalker &walker) {
226 walker.walk(param.getName());
227 walker.walk(param.getValue());
228 }
229 template <typename T>
230 static T replace(T param, AttrSubElementReplacements &attrRepls,
231 TypeSubElementReplacements &typeRepls) {
232 ArrayRef<Attribute> paramRepls = attrRepls.take_front(2);
233 return T(cast<decltype(param.getName())>(paramRepls[0]), paramRepls[1]);
234 }
235};
236
237//===----------------------------------------------------------------------===//
238// AttributeTraitBase
239//===----------------------------------------------------------------------===//
240
241namespace AttributeTrait {
242/// This class represents the base of an attribute trait.
243template <typename ConcreteType, template <typename> class TraitType>
245} // namespace AttributeTrait
246
247//===----------------------------------------------------------------------===//
248// AttributeInterface
249//===----------------------------------------------------------------------===//
250
251/// This class represents the base of an attribute interface. See the definition
252/// of `detail::Interface` for requirements on the `Traits` type.
253template <typename ConcreteType, typename Traits>
255 : public detail::Interface<ConcreteType, Attribute, Traits, Attribute,
256 AttributeTrait::TraitBase> {
257public:
259 using InterfaceBase = detail::Interface<ConcreteType, Attribute, Traits,
262
263protected:
264 /// Returns the impl interface instance for the given type.
266#ifndef NDEBUG
267 // Check that the current interface isn't an unresolved promise for the
268 // given attribute.
270 attr.getDialect(), attr.getTypeID(), ConcreteType::getInterfaceID(),
271 llvm::getTypeName<ConcreteType>());
272#endif
273
274 return attr.getAbstractAttribute().getInterface<ConcreteType>();
275 }
276
277 /// Allow access to 'getInterfaceFor'.
279};
280
281//===----------------------------------------------------------------------===//
282// Core AttributeTrait
283//===----------------------------------------------------------------------===//
284
285namespace AttributeTrait {
286/// This trait is used to determine if an attribute is mutable or not. It is
287/// attached on an attribute if the corresponding ConcreteType defines a
288/// `mutate` function with proper signature.
289template <typename ConcreteType>
291
292/// This trait is used to determine if an attribute is a location or not. It is
293/// attached to an attribute by the user if they intend the attribute to be used
294/// as a location.
295template <typename ConcreteType>
296struct IsLocation : public AttributeTrait::TraitBase<ConcreteType, IsLocation> {
297};
298} // namespace AttributeTrait
299
300} // namespace mlir.
301
302namespace llvm {
303
304// Attribute hash just like pointers.
305template <>
306struct DenseMapInfo<mlir::Attribute> {
307 static unsigned getHashValue(mlir::Attribute val) {
308 return mlir::hash_value(val);
309 }
311 return LHS == RHS;
312 }
313};
314template <typename T>
316 T, std::enable_if_t<std::is_base_of<mlir::Attribute, T>::value &&
317 !mlir::detail::IsInterface<T>::value>>
318 : public DenseMapInfo<mlir::Attribute> {
319};
320
321/// Allow LLVM to steal the low bits of Attributes.
322template <>
323struct PointerLikeTypeTraits<mlir::Attribute> {
324 static inline void *getAsVoidPointer(mlir::Attribute attr) {
325 return const_cast<void *>(attr.getAsOpaquePointer());
326 }
327 static inline mlir::Attribute getFromVoidPointer(void *ptr) {
329 }
330 static constexpr int NumLowBitsAvailable = llvm::PointerLikeTypeTraits<
332};
333
334template <>
335struct DenseMapInfo<mlir::NamedAttribute> {
336 static unsigned getHashValue(mlir::NamedAttribute val) {
337 return mlir::hash_value(val);
338 }
340 return lhs == rhs;
341 }
342};
343
344/// Add support for llvm style casts. We provide a cast between To and From if
345/// From is mlir::Attribute or derives from it.
346template <typename To, typename From>
347struct CastInfo<To, From,
348 std::enable_if_t<std::is_same_v<mlir::Attribute,
349 std::remove_const_t<From>> ||
350 std::is_base_of_v<mlir::Attribute, From>>>
352 DefaultDoCastIfPossible<To, From, CastInfo<To, From>> {
353 /// Arguments are taken as mlir::Attribute here and not as `From`, because
354 /// when casting from an intermediate type of the hierarchy to one of its
355 /// children, the val.getTypeID() inside T::classof will use the static
356 /// getTypeID of the parent instead of the non-static Type::getTypeID that
357 /// returns the dynamic ID. This means that T::classof would end up comparing
358 /// the static TypeID of the children to the static TypeID of its parent,
359 /// making it impossible to downcast from the parent to the child.
360 static inline bool isPossible(mlir::Attribute ty) {
361 /// Return a constant true instead of a dynamic true when casting to self or
362 /// up the hierarchy.
363 if constexpr (std::is_base_of_v<To, From>) {
364 return true;
365 } else {
366 return To::classof(ty);
367 }
368 }
369 static inline To doCast(mlir::Attribute attr) { return To(attr.getImpl()); }
370};
371
372} // namespace llvm
373
374#endif
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:256
detail::Interface< ConcreteType, Attribute, Traits, Attribute, AttributeTrait::TraitBase > InterfaceBase
Definition Attributes.h:259
AttributeInterface< ConcreteType, Traits > Base
Definition Attributes.h:258
static InterfaceBase::Concept * getInterfaceFor(Attribute attr)
Returns the impl interface instance for the given type.
Definition Attributes.h:265
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:127
ImplType * impl
Definition Attributes.h:149
bool operator!() const
Definition Attributes.h:48
const void * getAsOpaquePointer() const
Get an opaque pointer to the attribute.
Definition Attributes.h:75
Attribute(const ImplType *impl)
Definition Attributes.h:38
constexpr Attribute()=default
ImplType * getImpl() const
Return the internal Attribute implementation.
Definition Attributes.h:146
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:138
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:105
LLVM_DUMP_METHOD 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:117
AttributeStorage ImplType
Definition Attributes.h:33
const AbstractTy & getAbstractAttribute() const
Return the abstract descriptor for this attribute.
Definition Attributes.h:99
bool hasTrait()
Returns true if the type was registered with a particular trait.
Definition Attributes.h:94
Attribute(const Attribute &other)=default
bool hasPromiseOrImplementsInterface()
Returns true if InterfaceT has been promised by the dialect or implemented.
Definition Attributes.h:86
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:77
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:71
NamedAttribute represents a combination of a name and an Attribute value.
Definition Attributes.h:166
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:197
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:187
Attribute getValue() const
Return the value of the attribute.
Definition Attributes.h:181
bool operator!=(const NamedAttribute &rhs) const
Definition Attributes.h:200
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:241
detail::StorageUserTrait::IsMutable< ConcreteType > IsMutable
This trait is used to determine if an attribute is mutable or not.
Definition Attributes.h:290
detail::StorageUserTraitBase< ConcreteType, TraitType > TraitBase
This class represents the base of an attribute trait.
Definition Attributes.h:244
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:119
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:249
llvm::function_ref< Fn > function_ref
Definition LLVM.h:155
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:360
static bool isEqual(mlir::Attribute LHS, mlir::Attribute RHS)
Definition Attributes.h:310
static unsigned getHashValue(mlir::Attribute val)
Definition Attributes.h:307
static unsigned getHashValue(mlir::NamedAttribute val)
Definition Attributes.h:336
static bool isEqual(mlir::NamedAttribute lhs, mlir::NamedAttribute rhs)
Definition Attributes.h:339
static void * getAsVoidPointer(mlir::Attribute attr)
Definition Attributes.h:324
static mlir::Attribute getFromVoidPointer(void *ptr)
Definition Attributes.h:327
static void walk(T param, AttrTypeImmediateSubElementWalker &walker)
Definition Attributes.h:225
static T replace(T param, AttrSubElementReplacements &attrRepls, TypeSubElementReplacements &typeRepls)
Definition Attributes.h:230
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:296
This trait is used to determine if a storage user, like Type, is mutable or not.