MLIR  15.0.0git
Types.h
Go to the documentation of this file.
1 //===- Types.h - MLIR Type 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_TYPES_H
10 #define MLIR_IR_TYPES_H
11 
12 #include "mlir/IR/TypeSupport.h"
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/DenseMapInfo.h"
15 #include "llvm/Support/PointerLikeTypeTraits.h"
16 
17 namespace mlir {
18 /// Instances of the Type class are uniqued, have an immutable identifier and an
19 /// optional mutable component. They wrap a pointer to the storage object owned
20 /// by MLIRContext. Therefore, instances of Type are passed around by value.
21 ///
22 /// Some types are "primitives" meaning they do not have any parameters, for
23 /// example the Index type. Parametric types have additional information that
24 /// differentiates the types of the same class, for example the Integer type has
25 /// bitwidth, making i8 and i16 belong to the same kind by be different
26 /// instances of the IntegerType. Type parameters are part of the unique
27 /// immutable key. The mutable component of the type can be modified after the
28 /// type is created, but cannot affect the identity of the type.
29 ///
30 /// Types are constructed and uniqued via the 'detail::TypeUniquer' class.
31 ///
32 /// Derived type classes are expected to implement several required
33 /// implementation hooks:
34 /// * Optional:
35 /// - static LogicalResult verify(
36 /// function_ref<InFlightDiagnostic()> emitError,
37 /// Args... args)
38 /// * This method is invoked when calling the 'TypeBase::get/getChecked'
39 /// methods to ensure that the arguments passed in are valid to construct
40 /// a type instance with.
41 /// * This method is expected to return failure if a type cannot be
42 /// constructed with 'args', success otherwise.
43 /// * 'args' must correspond with the arguments passed into the
44 /// 'TypeBase::get' call.
45 ///
46 ///
47 /// Type storage objects inherit from TypeStorage and contain the following:
48 /// - The dialect that defined the type.
49 /// - Any parameters of the type.
50 /// - An optional mutable component.
51 /// For non-parametric types, a convenience DefaultTypeStorage is provided.
52 /// Parametric storage types must derive TypeStorage and respect the following:
53 /// - Define a type alias, KeyTy, to a type that uniquely identifies the
54 /// instance of the type.
55 /// * The key type must be constructible from the values passed into the
56 /// detail::TypeUniquer::get call.
57 /// * If the KeyTy does not have an llvm::DenseMapInfo specialization, the
58 /// storage class must define a hashing method:
59 /// 'static unsigned hashKey(const KeyTy &)'
60 ///
61 /// - Provide a method, 'bool operator==(const KeyTy &) const', to
62 /// compare the storage instance against an instance of the key type.
63 ///
64 /// - Provide a static construction method:
65 /// 'DerivedStorage *construct(TypeStorageAllocator &, const KeyTy &key)'
66 /// that builds a unique instance of the derived storage. The arguments to
67 /// this function are an allocator to store any uniqued data within the
68 /// context and the key type for this storage.
69 ///
70 /// - If they have a mutable component, this component must not be a part of
71 // the key.
72 class Type {
73 public:
74  /// Utility class for implementing types.
75  template <typename ConcreteType, typename BaseType, typename StorageType,
76  template <typename T> class... Traits>
77  using TypeBase = detail::StorageUserBase<ConcreteType, BaseType, StorageType,
78  detail::TypeUniquer, Traits...>;
79 
81 
83 
84  constexpr Type() {}
85  /* implicit */ Type(const ImplType *impl)
86  : impl(const_cast<ImplType *>(impl)) {}
87 
88  Type(const Type &other) = default;
89  Type &operator=(const Type &other) = default;
90 
91  bool operator==(Type other) const { return impl == other.impl; }
92  bool operator!=(Type other) const { return !(*this == other); }
93  explicit operator bool() const { return impl; }
94 
95  bool operator!() const { return impl == nullptr; }
96 
97  template <typename U> bool isa() const;
98  template <typename First, typename Second, typename... Rest> bool isa() const;
99  template <typename U> U dyn_cast() const;
100  template <typename U> U dyn_cast_or_null() const;
101  template <typename U> U cast() const;
102 
103  // Support type casting Type to itself.
104  static bool classof(Type) { return true; }
105 
106  /// Return a unique identifier for the concrete type. This is used to support
107  /// dynamic type casting.
108  TypeID getTypeID() { return impl->getAbstractType().getTypeID(); }
109 
110  /// Return the MLIRContext in which this type was uniqued.
111  MLIRContext *getContext() const;
112 
113  /// Get the dialect this type is registered to.
114  Dialect &getDialect() const { return impl->getAbstractType().getDialect(); }
115 
116  // Convenience predicates. This is only for floating point types,
117  // derived types should use isa/dyn_cast.
118  bool isIndex() const;
119  bool isBF16() const;
120  bool isF16() const;
121  bool isF32() const;
122  bool isF64() const;
123  bool isF80() const;
124  bool isF128() const;
125 
126  /// Return true if this is an integer type with the specified width.
127  bool isInteger(unsigned width) const;
128  /// Return true if this is a signless integer type (with the specified width).
129  bool isSignlessInteger() const;
130  bool isSignlessInteger(unsigned width) const;
131  /// Return true if this is a signed integer type (with the specified width).
132  bool isSignedInteger() const;
133  bool isSignedInteger(unsigned width) const;
134  /// Return true if this is an unsigned integer type (with the specified
135  /// width).
136  bool isUnsignedInteger() const;
137  bool isUnsignedInteger(unsigned width) const;
138 
139  /// Return the bit width of an integer or a float type, assert failure on
140  /// other types.
141  unsigned getIntOrFloatBitWidth() const;
142 
143  /// Return true if this is a signless integer or index type.
144  bool isSignlessIntOrIndex() const;
145  /// Return true if this is a signless integer, index, or float type.
146  bool isSignlessIntOrIndexOrFloat() const;
147  /// Return true of this is a signless integer or a float type.
148  bool isSignlessIntOrFloat() const;
149 
150  /// Return true if this is an integer (of any signedness) or an index type.
151  bool isIntOrIndex() const;
152  /// Return true if this is an integer (of any signedness) or a float type.
153  bool isIntOrFloat() const;
154  /// Return true if this is an integer (of any signedness), index, or float
155  /// type.
156  bool isIntOrIndexOrFloat() const;
157 
158  /// Print the current type.
159  void print(raw_ostream &os) const;
160  void dump() const;
161 
162  friend ::llvm::hash_code hash_value(Type arg);
163 
164  /// Methods for supporting PointerLikeTypeTraits.
165  const void *getAsOpaquePointer() const {
166  return static_cast<const void *>(impl);
167  }
168  static Type getFromOpaquePointer(const void *pointer) {
169  return Type(reinterpret_cast<ImplType *>(const_cast<void *>(pointer)));
170  }
171 
172  /// Returns true if the type was registered with a particular trait.
173  template <template <typename T> class Trait>
174  bool hasTrait() {
175  return getAbstractType().hasTrait<Trait>();
176  }
177 
178  /// Return the abstract type descriptor for this type.
179  const AbstractTy &getAbstractType() { return impl->getAbstractType(); }
180 
181 protected:
182  ImplType *impl{nullptr};
183 };
184 
185 inline raw_ostream &operator<<(raw_ostream &os, Type type) {
186  type.print(os);
187  return os;
188 }
189 
190 //===----------------------------------------------------------------------===//
191 // TypeTraitBase
192 //===----------------------------------------------------------------------===//
193 
194 namespace TypeTrait {
195 /// This class represents the base of a type trait.
196 template <typename ConcreteType, template <typename> class TraitType>
198 } // namespace TypeTrait
199 
200 //===----------------------------------------------------------------------===//
201 // TypeInterface
202 //===----------------------------------------------------------------------===//
203 
204 /// This class represents the base of a type interface. See the definition of
205 /// `detail::Interface` for requirements on the `Traits` type.
206 template <typename ConcreteType, typename Traits>
207 class TypeInterface : public detail::Interface<ConcreteType, Type, Traits, Type,
208  TypeTrait::TraitBase> {
209 public:
211  using InterfaceBase =
214 
215 private:
216  /// Returns the impl interface instance for the given type.
217  static typename InterfaceBase::Concept *getInterfaceFor(Type type) {
218  return type.getAbstractType().getInterface<ConcreteType>();
219  }
220 
221  /// Allow access to 'getInterfaceFor'.
222  friend InterfaceBase;
223 };
224 
225 //===----------------------------------------------------------------------===//
226 // Type Utils
227 //===----------------------------------------------------------------------===//
228 
229 // Make Type hashable.
230 inline ::llvm::hash_code hash_value(Type arg) {
232 }
233 
234 template <typename U> bool Type::isa() const {
235  assert(impl && "isa<> used on a null type.");
236  return U::classof(*this);
237 }
238 
239 template <typename First, typename Second, typename... Rest>
240 bool Type::isa() const {
241  return isa<First>() || isa<Second, Rest...>();
242 }
243 
244 template <typename U> U Type::dyn_cast() const {
245  return isa<U>() ? U(impl) : U(nullptr);
246 }
247 template <typename U> U Type::dyn_cast_or_null() const {
248  return (impl && isa<U>()) ? U(impl) : U(nullptr);
249 }
250 template <typename U> U Type::cast() const {
251  assert(isa<U>());
252  return U(impl);
253 }
254 
255 } // namespace mlir
256 
257 namespace llvm {
258 
259 // Type hash just like pointers.
260 template <> struct DenseMapInfo<mlir::Type> {
262  auto *pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
263  return mlir::Type(static_cast<mlir::Type::ImplType *>(pointer));
264  }
267  return mlir::Type(static_cast<mlir::Type::ImplType *>(pointer));
268  }
269  static unsigned getHashValue(mlir::Type val) { return mlir::hash_value(val); }
270  static bool isEqual(mlir::Type LHS, mlir::Type RHS) { return LHS == RHS; }
271 };
272 template <typename T>
273 struct DenseMapInfo<T, std::enable_if_t<std::is_base_of<mlir::Type, T>::value>>
274  : public DenseMapInfo<mlir::Type> {
275  static T getEmptyKey() {
276  const void *pointer = llvm::DenseMapInfo<const void *>::getEmptyKey();
277  return T::getFromOpaquePointer(pointer);
278  }
279  static T getTombstoneKey() {
281  return T::getFromOpaquePointer(pointer);
282  }
283 };
284 
285 /// We align TypeStorage by 8, so allow LLVM to steal the low bits.
286 template <> struct PointerLikeTypeTraits<mlir::Type> {
287 public:
288  static inline void *getAsVoidPointer(mlir::Type I) {
289  return const_cast<void *>(I.getAsOpaquePointer());
290  }
291  static inline mlir::Type getFromVoidPointer(void *P) {
293  }
294  static constexpr int NumLowBitsAvailable = 3;
295 };
296 
297 } // namespace llvm
298 
299 #endif // MLIR_IR_TYPES_H
bool operator!() const
Definition: Types.h:95
Include the generated interface declarations.
const void * getAsOpaquePointer() const
Methods for supporting PointerLikeTypeTraits.
Definition: Types.h:165
const AbstractTy & getAbstractType()
Return the abstract type descriptor for this type.
Definition: Types.h:179
bool isF32() const
Definition: Types.cpp:23
ImplType * impl
Definition: Types.h:182
Dialect & getDialect() const
Get the dialect this type is registered to.
Definition: Types.h:114
Explicitly register a set of "builtin" types.
Definition: CallGraph.h:221
constexpr Type()
Definition: Types.h:84
static bool isEqual(mlir::Type LHS, mlir::Type RHS)
Definition: Types.h:270
Type & operator=(const Type &other)=default
bool isIntOrIndexOrFloat() const
Return true if this is an integer (of any signedness), index, or float type.
Definition: Types.cpp:89
Base storage class appearing in a Type.
Definition: TypeSupport.h:121
bool isInteger(unsigned width) const
Return true if this is an integer type with the specified width.
Definition: Types.cpp:31
bool isIntOrFloat() const
Return true if this is an integer (of any signedness) or a float type.
Definition: Types.cpp:87
This class represents the base of a type interface.
Definition: Types.h:207
bool hasTrait() const
Returns true if the type has a particular trait.
Definition: TypeSupport.h:73
This class represents an abstract interface.
bool isUnsignedInteger() const
Return true if this is an unsigned integer type (with the specified width).
Definition: Types.cpp:61
raw_ostream & operator<<(raw_ostream &os, const AliasResult &result)
Definition: AliasAnalysis.h:78
This class contains all of the static information common to all instances of a registered Type...
Definition: TypeSupport.h:30
void print(raw_ostream &os) const
Print the current type.
This class provides an efficient unique identifier for a specific C++ type.
Definition: TypeID.h:104
static bool classof(Type)
Definition: Types.h:104
static unsigned getHashValue(mlir::Type val)
Definition: Types.h:269
bool isSignlessIntOrIndexOrFloat() const
Return true if this is a signless integer, index, or float type.
Definition: Types.cpp:77
bool isF80() const
Definition: Types.cpp:25
U dyn_cast_or_null() const
Definition: Types.h:247
static mlir::Type getFromVoidPointer(void *P)
Definition: Types.h:291
A utility class to get, or create, unique instances of types within an MLIRContext.
Definition: TypeSupport.h:165
U dyn_cast() const
Definition: Types.h:244
bool isF16() const
Definition: Types.cpp:22
T::Concept * getInterface() const
Returns an instance of the concept object for the given interface if it was registered to this type...
Definition: TypeSupport.h:62
bool isSignlessIntOrIndex() const
Return true if this is a signless integer or index type.
Definition: Types.cpp:73
bool isIndex() const
Definition: Types.cpp:28
Dialects are groups of MLIR operations, types and attributes, as well as behavior associated with the...
Definition: Dialect.h:41
static Type getFromOpaquePointer(const void *pointer)
Definition: Types.h:168
bool isSignlessInteger() const
Return true if this is a signless integer type (with the specified width).
Definition: Types.cpp:37
bool isF128() const
Definition: Types.cpp:26
bool isSignedInteger() const
Return true if this is a signed integer type (with the specified width).
Definition: Types.cpp:49
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Definition: Types.h:72
bool operator==(Type other) const
Definition: Types.h:91
MLIRContext * getContext() const
Return the MLIRContext in which this type was uniqued.
Definition: Types.cpp:19
inline ::llvm::hash_code hash_value(AffineExpr arg)
Make AffineExpr hashable.
Definition: AffineExpr.h:240
bool isF64() const
Definition: Types.cpp:24
void dump() const
TypeID getTypeID()
Return a unique identifier for the concrete type.
Definition: Types.h:108
Type(const ImplType *impl)
Definition: Types.h:85
friend ::llvm::hash_code hash_value(Type arg)
Definition: Types.h:230
Utility class for implementing users of storage classes uniqued by a StorageUniquer.
MLIRContext is the top-level object for a collection of MLIR operations.
Definition: MLIRContext.h:55
unsigned getIntOrFloatBitWidth() const
Return the bit width of an integer or a float type, assert failure on other types.
Definition: Types.cpp:91
bool isIntOrIndex() const
Return true if this is an integer (of any signedness) or an index type.
Definition: Types.cpp:85
static void * getAsVoidPointer(mlir::Type I)
Definition: Types.h:288
bool isSignlessIntOrFloat() const
Return true of this is a signless integer or a float type.
Definition: Types.cpp:81
static mlir::Type getTombstoneKey()
Definition: Types.h:265
bool hasTrait()
Returns true if the type was registered with a particular trait.
Definition: Types.h:174
Helper class for implementing traits for storage classes.
bool isa() const
Definition: Types.h:234
static mlir::Type getEmptyKey()
Definition: Types.h:261
bool isBF16() const
Definition: Types.cpp:21
U cast() const
Definition: Types.h:250
bool operator!=(Type other) const
Definition: Types.h:92