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
12 #include "mlir/IR/AttributeSupport.h"
13 #include "llvm/Support/PointerLikeTypeTraits.h"
14
15 namespace mlir {
16 class Identifier;
17
18 /// Attributes are known-constant values of operations.
19 ///
20 /// Instances of the Attribute class are references to immortal key-value pairs
21 /// with immutable, uniqued keys owned by MLIRContext. As such, an Attribute is
22 /// a thin wrapper around an underlying storage pointer. Attributes are usually
23 /// passed by value.
24 class Attribute {
25 public:
26 /// Utility class for implementing attributes.
27 template <typename ConcreteType, typename BaseType, typename StorageType,
28 template <typename T> class... Traits>
29 using AttrBase = detail::StorageUserBase<ConcreteType, BaseType, StorageType,
30 detail::AttributeUniquer, Traits...>;
31
32 using ImplType = AttributeStorage;
33 using ValueType = void;
34
Attribute()35 constexpr Attribute() : impl(nullptr) {}
Attribute(const ImplType * impl)36 /* implicit */ Attribute(const ImplType *impl)
37 : impl(const_cast<ImplType *>(impl)) {}
38
39 Attribute(const Attribute &other) = default;
40 Attribute &operator=(const Attribute &other) = default;
41
42 bool operator==(Attribute other) const { return impl == other.impl; }
43 bool operator!=(Attribute other) const { return !(*this == other); }
44 explicit operator bool() const { return impl; }
45
46 bool operator!() const { return impl == nullptr; }
47
48 template <typename U> bool isa() const;
49 template <typename First, typename Second, typename... Rest>
50 bool isa() const;
51 template <typename U> U dyn_cast() const;
52 template <typename U> U dyn_cast_or_null() const;
53 template <typename U> U cast() const;
54
55 // Support dyn_cast'ing Attribute to itself.
classof(Attribute)56 static bool classof(Attribute) { return true; }
57
58 /// Return a unique identifier for the concrete attribute type. This is used
59 /// to support dynamic type casting.
getTypeID()60 TypeID getTypeID() { return impl->getAbstractAttribute().getTypeID(); }
61
62 /// Return the type of this attribute.
63 Type getType() const;
64
65 /// Return the context this attribute belongs to.
66 MLIRContext *getContext() const;
67
68 /// Get the dialect this attribute is registered to.
69 Dialect &getDialect() const;
70
71 /// Print the attribute.
72 void print(raw_ostream &os) const;
73 void dump() const;
74
75 /// Get an opaque pointer to the attribute.
getAsOpaquePointer()76 const void *getAsOpaquePointer() const { return impl; }
77 /// Construct an attribute from the opaque pointer representation.
getFromOpaquePointer(const void * ptr)78 static Attribute getFromOpaquePointer(const void *ptr) {
79 return Attribute(reinterpret_cast<const ImplType *>(ptr));
80 }
81
82 friend ::llvm::hash_code hash_value(Attribute arg);
83
84 /// Return the abstract descriptor for this attribute.
getAbstractAttribute()85 const AbstractAttribute &getAbstractAttribute() const {
86 return impl->getAbstractAttribute();
87 }
88
89 protected:
90 ImplType *impl;
91 };
92
93 inline raw_ostream &operator<<(raw_ostream &os, Attribute attr) {
94 attr.print(os);
95 return os;
96 }
97
isa()98 template <typename U> bool Attribute::isa() const {
99 assert(impl && "isa<> used on a null attribute.");
100 return U::classof(*this);
101 }
102
103 template <typename First, typename Second, typename... Rest>
isa()104 bool Attribute::isa() const {
105 return isa<First>() || isa<Second, Rest...>();
106 }
107
dyn_cast()108 template <typename U> U Attribute::dyn_cast() const {
109 return isa<U>() ? U(impl) : U(nullptr);
110 }
dyn_cast_or_null()111 template <typename U> U Attribute::dyn_cast_or_null() const {
112 return (impl && isa<U>()) ? U(impl) : U(nullptr);
113 }
cast()114 template <typename U> U Attribute::cast() const {
115 assert(isa<U>());
116 return U(impl);
117 }
118
hash_value(Attribute arg)119 inline ::llvm::hash_code hash_value(Attribute arg) {
120 return ::llvm::hash_value(arg.impl);
121 }
122
123 //===----------------------------------------------------------------------===//
124 // NamedAttribute
125 //===----------------------------------------------------------------------===//
126
127 /// NamedAttribute is combination of a name, represented by an Identifier, and a
128 /// value, represented by an Attribute. The attribute pointer should always be
129 /// non-null.
130 using NamedAttribute = std::pair<Identifier, Attribute>;
131
132 bool operator<(const NamedAttribute &lhs, const NamedAttribute &rhs);
133 bool operator<(const NamedAttribute &lhs, StringRef rhs);
134
135 //===----------------------------------------------------------------------===//
136 // AttributeTraitBase
137 //===----------------------------------------------------------------------===//
138
139 namespace AttributeTrait {
140 /// This class represents the base of an attribute trait.
141 template <typename ConcreteType, template <typename> class TraitType>
142 using TraitBase = detail::StorageUserTraitBase<ConcreteType, TraitType>;
143 } // namespace AttributeTrait
144
145 //===----------------------------------------------------------------------===//
146 // AttributeInterface
147 //===----------------------------------------------------------------------===//
148
149 /// This class represents the base of an attribute interface. See the definition
150 /// of `detail::Interface` for requirements on the `Traits` type.
151 template <typename ConcreteType, typename Traits>
152 class AttributeInterface
153 : public detail::Interface<ConcreteType, Attribute, Traits, Attribute,
154 AttributeTrait::TraitBase> {
155 public:
156 using Base = AttributeInterface<ConcreteType, Traits>;
157 using InterfaceBase = detail::Interface<ConcreteType, Attribute, Traits,
158 Attribute, AttributeTrait::TraitBase>;
159 using InterfaceBase::InterfaceBase;
160
161 private:
162 /// Returns the impl interface instance for the given type.
getInterfaceFor(Attribute attr)163 static typename InterfaceBase::Concept *getInterfaceFor(Attribute attr) {
164 return attr.getAbstractAttribute().getInterface<ConcreteType>();
165 }
166
167 /// Allow access to 'getInterfaceFor'.
168 friend InterfaceBase;
169 };
170
171 } // end namespace mlir.
172
173 namespace llvm {
174
175 // Attribute hash just like pointers.
176 template <> struct DenseMapInfo<mlir::Attribute> {
177 static mlir::Attribute getEmptyKey() {
178 auto pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
179 return mlir::Attribute(static_cast<mlir::Attribute::ImplType *>(pointer));
180 }
181 static mlir::Attribute getTombstoneKey() {
182 auto pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
183 return mlir::Attribute(static_cast<mlir::Attribute::ImplType *>(pointer));
184 }
185 static unsigned getHashValue(mlir::Attribute val) {
186 return mlir::hash_value(val);
187 }
188 static bool isEqual(mlir::Attribute LHS, mlir::Attribute RHS) {
189 return LHS == RHS;
190 }
191 };
192
193 /// Allow LLVM to steal the low bits of Attributes.
194 template <> struct PointerLikeTypeTraits<mlir::Attribute> {
195 static inline void *getAsVoidPointer(mlir::Attribute attr) {
196 return const_cast<void *>(attr.getAsOpaquePointer());
197 }
198 static inline mlir::Attribute getFromVoidPointer(void *ptr) {
199 return mlir::Attribute::getFromOpaquePointer(ptr);
200 }
201 static constexpr int NumLowBitsAvailable = llvm::PointerLikeTypeTraits<
202 mlir::AttributeStorage *>::NumLowBitsAvailable;
203 };
204
205 } // namespace llvm
206
207 #endif
208