/home/arjun/llvm-project/mlir/include/mlir/IR/Types.h
Line | Count | Source (jump to first uncovered line) |
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 | | class FloatType; |
19 | | class Identifier; |
20 | | class IndexType; |
21 | | class IntegerType; |
22 | | class MLIRContext; |
23 | | class TypeStorage; |
24 | | |
25 | | namespace detail { |
26 | | struct FunctionTypeStorage; |
27 | | struct OpaqueTypeStorage; |
28 | | } // namespace detail |
29 | | |
30 | | /// Instances of the Type class are immutable and uniqued. They wrap a pointer |
31 | | /// to the storage object owned by MLIRContext. Therefore, instances of Type |
32 | | /// are passed around by value. |
33 | | /// |
34 | | /// Some types are "primitives" meaning they do not have any parameters, for |
35 | | /// example the Index type. Parametric types have additional information that |
36 | | /// differentiates the types of the same kind between them, for example the |
37 | | /// Integer type has bitwidth, making i8 and i16 belong to the same kind by be |
38 | | /// different instances of the IntegerType. |
39 | | /// |
40 | | /// Types are constructed and uniqued via the 'detail::TypeUniquer' class. |
41 | | /// |
42 | | /// Derived type classes are expected to implement several required |
43 | | /// implementation hooks: |
44 | | /// * Required: |
45 | | /// - static bool kindof(unsigned kind); |
46 | | /// * Returns if the provided type kind corresponds to an instance of the |
47 | | /// current type. Used for isa/dyn_cast casting functionality. |
48 | | /// |
49 | | /// * Optional: |
50 | | /// - static LogicalResult verifyConstructionInvariants(Location loc, |
51 | | /// Args... args) |
52 | | /// * This method is invoked when calling the 'TypeBase::get/getChecked' |
53 | | /// methods to ensure that the arguments passed in are valid to construct |
54 | | /// a type instance with. |
55 | | /// * This method is expected to return failure if a type cannot be |
56 | | /// constructed with 'args', success otherwise. |
57 | | /// * 'args' must correspond with the arguments passed into the |
58 | | /// 'TypeBase::get' call after the type kind. |
59 | | /// |
60 | | /// |
61 | | /// Type storage objects inherit from TypeStorage and contain the following: |
62 | | /// - The type kind (for LLVM-style RTTI). |
63 | | /// - The dialect that defined the type. |
64 | | /// - Any parameters of the type. |
65 | | /// For non-parametric types, a convenience DefaultTypeStorage is provided. |
66 | | /// Parametric storage types must derive TypeStorage and respect the following: |
67 | | /// - Define a type alias, KeyTy, to a type that uniquely identifies the |
68 | | /// instance of the type within its kind. |
69 | | /// * The key type must be constructible from the values passed into the |
70 | | /// detail::TypeUniquer::get call after the type kind. |
71 | | /// * If the KeyTy does not have an llvm::DenseMapInfo specialization, the |
72 | | /// storage class must define a hashing method: |
73 | | /// 'static unsigned hashKey(const KeyTy &)' |
74 | | /// |
75 | | /// - Provide a method, 'bool operator==(const KeyTy &) const', to |
76 | | /// compare the storage instance against an instance of the key type. |
77 | | /// |
78 | | /// - Provide a construction method: |
79 | | /// 'DerivedStorage *construct(TypeStorageAllocator &, const KeyTy &key)' |
80 | | /// that builds a unique instance of the derived storage. The arguments to |
81 | | /// this function are an allocator to store any uniqued data within the |
82 | | /// context and the key type for this storage. |
83 | | class Type { |
84 | | public: |
85 | | /// Integer identifier for all the concrete type kinds. |
86 | | /// Note: This is not an enum class as each dialect will likely define a |
87 | | /// separate enumeration for the specific types that they define. Not being an |
88 | | /// enum class also simplifies the handling of type kinds by not requiring |
89 | | /// casts for each use. |
90 | | enum Kind { |
91 | | // Builtin types. |
92 | | Function, |
93 | | Opaque, |
94 | | LAST_BUILTIN_TYPE = Opaque, |
95 | | |
96 | | // Reserve type kinds for dialect specific type system extensions. |
97 | | #define DEFINE_SYM_KIND_RANGE(Dialect) \ |
98 | | FIRST_##Dialect##_TYPE, LAST_##Dialect##_TYPE = FIRST_##Dialect##_TYPE + 0xff, |
99 | | #include "DialectSymbolRegistry.def" |
100 | | }; |
101 | | |
102 | | /// Utility class for implementing types. |
103 | | template <typename ConcreteType, typename BaseType, |
104 | | typename StorageType = DefaultTypeStorage> |
105 | | using TypeBase = detail::StorageUserBase<ConcreteType, BaseType, StorageType, |
106 | | detail::TypeUniquer>; |
107 | | |
108 | | using ImplType = TypeStorage; |
109 | | |
110 | 0 | constexpr Type() : impl(nullptr) {} |
111 | | /* implicit */ Type(const ImplType *impl) |
112 | 0 | : impl(const_cast<ImplType *>(impl)) {} |
113 | | |
114 | | Type(const Type &other) = default; |
115 | | Type &operator=(const Type &other) = default; |
116 | | |
117 | 0 | bool operator==(Type other) const { return impl == other.impl; } |
118 | 0 | bool operator!=(Type other) const { return !(*this == other); } |
119 | 0 | explicit operator bool() const { return impl; } |
120 | | |
121 | 0 | bool operator!() const { return impl == nullptr; } |
122 | | |
123 | | template <typename U> bool isa() const; |
124 | | template <typename U> U dyn_cast() const; |
125 | | template <typename U> U dyn_cast_or_null() const; |
126 | | template <typename U> U cast() const; |
127 | | |
128 | | // Support type casting Type to itself. |
129 | 0 | static bool classof(Type) { return true; } |
130 | | |
131 | | /// Return the classification for this type. |
132 | | unsigned getKind() const; |
133 | | |
134 | | /// Return the LLVMContext in which this type was uniqued. |
135 | | MLIRContext *getContext() const; |
136 | | |
137 | | /// Get the dialect this type is registered to. |
138 | | Dialect &getDialect() const; |
139 | | |
140 | | // Convenience predicates. This is only for floating point types, |
141 | | // derived types should use isa/dyn_cast. |
142 | | bool isIndex(); |
143 | | bool isBF16(); |
144 | | bool isF16(); |
145 | | bool isF32(); |
146 | | bool isF64(); |
147 | | |
148 | | /// Return true if this is an integer type with the specified width. |
149 | | bool isInteger(unsigned width); |
150 | | /// Return true if this is a signless integer type (with the specified width). |
151 | | bool isSignlessInteger(); |
152 | | bool isSignlessInteger(unsigned width); |
153 | | /// Return true if this is a signed integer type (with the specified width). |
154 | | bool isSignedInteger(); |
155 | | bool isSignedInteger(unsigned width); |
156 | | /// Return true if this is an unsigned integer type (with the specified |
157 | | /// width). |
158 | | bool isUnsignedInteger(); |
159 | | bool isUnsignedInteger(unsigned width); |
160 | | |
161 | | /// Return the bit width of an integer or a float type, assert failure on |
162 | | /// other types. |
163 | | unsigned getIntOrFloatBitWidth(); |
164 | | |
165 | | /// Return true if this is a signless integer or index type. |
166 | | bool isSignlessIntOrIndex(); |
167 | | /// Return true if this is a signless integer, index, or float type. |
168 | | bool isSignlessIntOrIndexOrFloat(); |
169 | | /// Return true of this is a signless integer or a float type. |
170 | | bool isSignlessIntOrFloat(); |
171 | | |
172 | | /// Return true if this is an integer (of any signedness) or an index type. |
173 | | bool isIntOrIndex(); |
174 | | /// Return true if this is an integer (of any signedness) or a float type. |
175 | | bool isIntOrFloat(); |
176 | | /// Return true if this is an integer (of any signedness), index, or float |
177 | | /// type. |
178 | | bool isIntOrIndexOrFloat(); |
179 | | |
180 | | /// Print the current type. |
181 | | void print(raw_ostream &os); |
182 | | void dump(); |
183 | | |
184 | | friend ::llvm::hash_code hash_value(Type arg); |
185 | | |
186 | | unsigned getSubclassData() const; |
187 | | void setSubclassData(unsigned val); |
188 | | |
189 | | /// Methods for supporting PointerLikeTypeTraits. |
190 | 0 | const void *getAsOpaquePointer() const { |
191 | 0 | return static_cast<const void *>(impl); |
192 | 0 | } |
193 | 0 | static Type getFromOpaquePointer(const void *pointer) { |
194 | 0 | return Type(reinterpret_cast<ImplType *>(const_cast<void *>(pointer))); |
195 | 0 | } |
196 | | |
197 | | protected: |
198 | | ImplType *impl; |
199 | | }; |
200 | | |
201 | 0 | inline raw_ostream &operator<<(raw_ostream &os, Type type) { |
202 | 0 | type.print(os); |
203 | 0 | return os; |
204 | 0 | } |
205 | | |
206 | | /// Function types map from a list of inputs to a list of results. |
207 | | class FunctionType |
208 | | : public Type::TypeBase<FunctionType, Type, detail::FunctionTypeStorage> { |
209 | | public: |
210 | | using Base::Base; |
211 | | |
212 | | static FunctionType get(ArrayRef<Type> inputs, ArrayRef<Type> results, |
213 | | MLIRContext *context); |
214 | | |
215 | | // Input types. |
216 | 0 | unsigned getNumInputs() const { return getSubclassData(); } |
217 | | |
218 | 0 | Type getInput(unsigned i) const { return getInputs()[i]; } |
219 | | |
220 | | ArrayRef<Type> getInputs() const; |
221 | | |
222 | | // Result types. |
223 | | unsigned getNumResults() const; |
224 | | |
225 | 0 | Type getResult(unsigned i) const { return getResults()[i]; } |
226 | | |
227 | | ArrayRef<Type> getResults() const; |
228 | | |
229 | | /// Methods for support type inquiry through isa, cast, and dyn_cast. |
230 | 0 | static bool kindof(unsigned kind) { return kind == Kind::Function; } |
231 | | }; |
232 | | |
233 | | /// Opaque types represent types of non-registered dialects. These are types |
234 | | /// represented in their raw string form, and can only usefully be tested for |
235 | | /// type equality. |
236 | | class OpaqueType |
237 | | : public Type::TypeBase<OpaqueType, Type, detail::OpaqueTypeStorage> { |
238 | | public: |
239 | | using Base::Base; |
240 | | |
241 | | /// Get or create a new OpaqueType with the provided dialect and string data. |
242 | | static OpaqueType get(Identifier dialect, StringRef typeData, |
243 | | MLIRContext *context); |
244 | | |
245 | | /// Get or create a new OpaqueType with the provided dialect and string data. |
246 | | /// If the given identifier is not a valid namespace for a dialect, then a |
247 | | /// null type is returned. |
248 | | static OpaqueType getChecked(Identifier dialect, StringRef typeData, |
249 | | MLIRContext *context, Location location); |
250 | | |
251 | | /// Returns the dialect namespace of the opaque type. |
252 | | Identifier getDialectNamespace() const; |
253 | | |
254 | | /// Returns the raw type data of the opaque type. |
255 | | StringRef getTypeData() const; |
256 | | |
257 | | /// Verify the construction of an opaque type. |
258 | | static LogicalResult verifyConstructionInvariants(Location loc, |
259 | | Identifier dialect, |
260 | | StringRef typeData); |
261 | | |
262 | 0 | static bool kindof(unsigned kind) { return kind == Kind::Opaque; } |
263 | | }; |
264 | | |
265 | | // Make Type hashable. |
266 | 0 | inline ::llvm::hash_code hash_value(Type arg) { |
267 | 0 | return ::llvm::hash_value(arg.impl); |
268 | 0 | } |
269 | | |
270 | 0 | template <typename U> bool Type::isa() const { |
271 | 0 | assert(impl && "isa<> used on a null type."); |
272 | 0 | return U::classof(*this); |
273 | 0 | } Unexecuted instantiation: _ZNK4mlir4Type3isaINS_11IntegerTypeEEEbv Unexecuted instantiation: _ZNK4mlir4Type3isaINS_9FloatTypeEEEbv Unexecuted instantiation: _ZNK4mlir4Type3isaINS_11ComplexTypeEEEbv Unexecuted instantiation: _ZNK4mlir4Type3isaINS_10OpaqueTypeEEEbv Unexecuted instantiation: _ZNK4mlir4Type3isaINS_10VectorTypeEEEbv Unexecuted instantiation: _ZNK4mlir4Type3isaINS_9IndexTypeEEEbv Unexecuted instantiation: _ZNK4mlir4Type3isaINS_10MemRefTypeEEEbv Unexecuted instantiation: _ZNK4mlir4Type3isaINS_12FunctionTypeEEEbv Unexecuted instantiation: _ZNK4mlir4Type3isaINS_10TensorTypeEEEbv Unexecuted instantiation: _ZNK4mlir4Type3isaINS_18UnrankedMemRefTypeEEEbv Unexecuted instantiation: _ZNK4mlir4Type3isaINS_16RankedTensorTypeEEEbv Unexecuted instantiation: _ZNK4mlir4Type3isaINS_18UnrankedTensorTypeEEEbv Unexecuted instantiation: _ZNK4mlir4Type3isaINS_8NoneTypeEEEbv Unexecuted instantiation: _ZNK4mlir4Type3isaINS_10ShapedTypeEEEbv Unexecuted instantiation: _ZNK4mlir4Type3isaINS_9TupleTypeEEEbv |
274 | 0 | template <typename U> U Type::dyn_cast() const { |
275 | 0 | return isa<U>() ? U(impl) : U(nullptr); |
276 | 0 | } Unexecuted instantiation: _ZNK4mlir4Type8dyn_castINS_10MemRefTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type8dyn_castINS_10VectorTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type8dyn_castINS_16RankedTensorTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type8dyn_castINS_11IntegerTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type8dyn_castINS_10ShapedTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type8dyn_castINS_9FloatTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type8dyn_castINS_18UnrankedMemRefTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type8dyn_castINS_10TensorTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type8dyn_castINS_12FunctionTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type8dyn_castINS_11ComplexTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type8dyn_castINS_9TupleTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type8dyn_castINS_10OpaqueTypeEEET_v |
277 | | template <typename U> U Type::dyn_cast_or_null() const { |
278 | | return (impl && isa<U>()) ? U(impl) : U(nullptr); |
279 | | } |
280 | 0 | template <typename U> U Type::cast() const { |
281 | 0 | assert(isa<U>()); |
282 | 0 | return U(impl); |
283 | 0 | } Unexecuted instantiation: _ZNK4mlir4Type4castINS_10MemRefTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type4castINS_10VectorTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type4castINS_10TensorTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type4castINS_12FunctionTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type4castINS_11IntegerTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type4castINS_10ShapedTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type4castINS_11ComplexTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type4castINS_10OpaqueTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type4castINS_16RankedTensorTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type4castINS_18UnrankedTensorTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type4castINS_18UnrankedMemRefTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type4castINS_9TupleTypeEEET_v Unexecuted instantiation: _ZNK4mlir4Type4castINS_9FloatTypeEEET_v |
284 | | |
285 | | } // end namespace mlir |
286 | | |
287 | | namespace llvm { |
288 | | |
289 | | // Type hash just like pointers. |
290 | | template <> struct DenseMapInfo<mlir::Type> { |
291 | 0 | static mlir::Type getEmptyKey() { |
292 | 0 | auto pointer = llvm::DenseMapInfo<void *>::getEmptyKey(); |
293 | 0 | return mlir::Type(static_cast<mlir::Type::ImplType *>(pointer)); |
294 | 0 | } |
295 | 0 | static mlir::Type getTombstoneKey() { |
296 | 0 | auto pointer = llvm::DenseMapInfo<void *>::getTombstoneKey(); |
297 | 0 | return mlir::Type(static_cast<mlir::Type::ImplType *>(pointer)); |
298 | 0 | } |
299 | 0 | static unsigned getHashValue(mlir::Type val) { return mlir::hash_value(val); } |
300 | 0 | static bool isEqual(mlir::Type LHS, mlir::Type RHS) { return LHS == RHS; } |
301 | | }; |
302 | | |
303 | | /// We align TypeStorage by 8, so allow LLVM to steal the low bits. |
304 | | template <> struct PointerLikeTypeTraits<mlir::Type> { |
305 | | public: |
306 | 0 | static inline void *getAsVoidPointer(mlir::Type I) { |
307 | 0 | return const_cast<void *>(I.getAsOpaquePointer()); |
308 | 0 | } |
309 | 0 | static inline mlir::Type getFromVoidPointer(void *P) { |
310 | 0 | return mlir::Type::getFromOpaquePointer(P); |
311 | 0 | } |
312 | | static constexpr int NumLowBitsAvailable = 3; |
313 | | }; |
314 | | |
315 | | } // namespace llvm |
316 | | |
317 | | #endif // MLIR_IR_TYPES_H |