• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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