1 //===- LLVMDialect.h - MLIR LLVM dialect types ------------------*- 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 // This file defines the types for the LLVM dialect in MLIR. These MLIR types
10 // correspond to the LLVM IR type system.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef MLIR_DIALECT_LLVMIR_LLVMTYPES_H_
15 #define MLIR_DIALECT_LLVMIR_LLVMTYPES_H_
16 
17 #include "mlir/IR/Types.h"
18 #include "mlir/Interfaces/DataLayoutInterfaces.h"
19 
20 namespace llvm {
21 class ElementCount;
22 class TypeSize;
23 } // namespace llvm
24 
25 namespace mlir {
26 
27 class DialectAsmParser;
28 class DialectAsmPrinter;
29 
30 namespace LLVM {
31 class LLVMDialect;
32 
33 namespace detail {
34 struct LLVMFunctionTypeStorage;
35 struct LLVMPointerTypeStorage;
36 struct LLVMStructTypeStorage;
37 struct LLVMTypeAndSizeStorage;
38 } // namespace detail
39 } // namespace LLVM
40 } // namespace mlir
41 
42 #include "mlir/Dialect/LLVMIR/LLVMTypeInterfaces.h.inc"
43 
44 namespace mlir {
45 namespace LLVM {
46 
47 //===----------------------------------------------------------------------===//
48 // Trivial types.
49 //===----------------------------------------------------------------------===//
50 
51 // Batch-define trivial types.
52 #define DEFINE_TRIVIAL_LLVM_TYPE(ClassName)                                    \
53   class ClassName : public Type::TypeBase<ClassName, Type, TypeStorage> {      \
54   public:                                                                      \
55     using Base::Base;                                                          \
56   }
57 
58 DEFINE_TRIVIAL_LLVM_TYPE(LLVMVoidType);
59 DEFINE_TRIVIAL_LLVM_TYPE(LLVMPPCFP128Type);
60 DEFINE_TRIVIAL_LLVM_TYPE(LLVMX86MMXType);
61 DEFINE_TRIVIAL_LLVM_TYPE(LLVMTokenType);
62 DEFINE_TRIVIAL_LLVM_TYPE(LLVMLabelType);
63 DEFINE_TRIVIAL_LLVM_TYPE(LLVMMetadataType);
64 
65 #undef DEFINE_TRIVIAL_LLVM_TYPE
66 
67 //===----------------------------------------------------------------------===//
68 // LLVMArrayType.
69 //===----------------------------------------------------------------------===//
70 
71 /// LLVM dialect array type. It is an aggregate type representing consecutive
72 /// elements in memory, parameterized by the number of elements and the element
73 /// type.
74 class LLVMArrayType : public Type::TypeBase<LLVMArrayType, Type,
75                                             detail::LLVMTypeAndSizeStorage> {
76 public:
77   /// Inherit base constructors.
78   using Base::Base;
79   using Base::getChecked;
80 
81   /// Checks if the given type can be used inside an array type.
82   static bool isValidElementType(Type type);
83 
84   /// Gets or creates an instance of LLVM dialect array type containing
85   /// `numElements` of `elementType`, in the same context as `elementType`.
86   static LLVMArrayType get(Type elementType, unsigned numElements);
87   static LLVMArrayType getChecked(function_ref<InFlightDiagnostic()> emitError,
88                                   Type elementType, unsigned numElements);
89 
90   /// Returns the element type of the array.
91   Type getElementType();
92 
93   /// Returns the number of elements in the array type.
94   unsigned getNumElements();
95 
96   /// Verifies that the type about to be constructed is well-formed.
97   static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
98                               Type elementType, unsigned numElements);
99 };
100 
101 //===----------------------------------------------------------------------===//
102 // LLVMFunctionType.
103 //===----------------------------------------------------------------------===//
104 
105 /// LLVM dialect function type. It consists of a single return type (unlike MLIR
106 /// which can have multiple), a list of parameter types and can optionally be
107 /// variadic.
108 class LLVMFunctionType
109     : public Type::TypeBase<LLVMFunctionType, Type,
110                             detail::LLVMFunctionTypeStorage> {
111 public:
112   /// Inherit base constructors.
113   using Base::Base;
114   using Base::getChecked;
115 
116   /// Checks if the given type can be used an argument in a function type.
117   static bool isValidArgumentType(Type type);
118 
119   /// Checks if the given type can be used as a result in a function type.
120   static bool isValidResultType(Type type);
121 
122   /// Returns whether the function is variadic.
123   bool isVarArg();
124 
125   /// Gets or creates an instance of LLVM dialect function in the same context
126   /// as the `result` type.
127   static LLVMFunctionType get(Type result, ArrayRef<Type> arguments,
128                               bool isVarArg = false);
129   static LLVMFunctionType
130   getChecked(function_ref<InFlightDiagnostic()> emitError, Type result,
131              ArrayRef<Type> arguments, bool isVarArg = false);
132 
133   /// Returns the result type of the function.
134   Type getReturnType();
135 
136   /// Returns the number of arguments to the function.
137   unsigned getNumParams();
138 
139   /// Returns `i`-th argument of the function. Asserts on out-of-bounds.
140   Type getParamType(unsigned i);
141 
142   /// Returns a list of argument types of the function.
143   ArrayRef<Type> getParams();
params()144   ArrayRef<Type> params() { return getParams(); }
145 
146   /// Verifies that the type about to be constructed is well-formed.
147   static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
148                               Type result, ArrayRef<Type> arguments, bool);
149 };
150 
151 //===----------------------------------------------------------------------===//
152 // LLVMPointerType.
153 //===----------------------------------------------------------------------===//
154 
155 /// LLVM dialect pointer type. This type typically represents a reference to an
156 /// object in memory. It is parameterized by the element type and the address
157 /// space.
158 class LLVMPointerType : public Type::TypeBase<LLVMPointerType, Type,
159                                               detail::LLVMPointerTypeStorage,
160                                               DataLayoutTypeInterface::Trait> {
161 public:
162   /// Inherit base constructors.
163   using Base::Base;
164   using Base::getChecked;
165 
166   /// Checks if the given type can have a pointer type pointing to it.
167   static bool isValidElementType(Type type);
168 
169   /// Gets or creates an instance of LLVM dialect pointer type pointing to an
170   /// object of `pointee` type in the given address space. The pointer type is
171   /// created in the same context as `pointee`.
172   static LLVMPointerType get(Type pointee, unsigned addressSpace = 0);
173   static LLVMPointerType
174   getChecked(function_ref<InFlightDiagnostic()> emitError, Type pointee,
175              unsigned addressSpace = 0);
176 
177   /// Returns the pointed-to type.
178   Type getElementType() const;
179 
180   /// Returns the address space of the pointer.
181   unsigned getAddressSpace() const;
182 
183   /// Verifies that the type about to be constructed is well-formed.
184   static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
185                               Type pointee, unsigned);
186 
187   /// Hooks for DataLayoutTypeInterface. Should not be called directly. Obtain a
188   /// DataLayout instance and query it instead.
189   unsigned getTypeSizeInBits(const DataLayout &dataLayout,
190                              DataLayoutEntryListRef params) const;
191   unsigned getABIAlignment(const DataLayout &dataLayout,
192                            DataLayoutEntryListRef params) const;
193   unsigned getPreferredAlignment(const DataLayout &dataLayout,
194                                  DataLayoutEntryListRef params) const;
195   bool areCompatible(DataLayoutEntryListRef oldLayout,
196                      DataLayoutEntryListRef newLayout) const;
197   LogicalResult verifyEntries(DataLayoutEntryListRef entries,
198                               Location loc) const;
199 };
200 
201 //===----------------------------------------------------------------------===//
202 // LLVMStructType.
203 //===----------------------------------------------------------------------===//
204 
205 /// LLVM dialect structure type representing a collection of different-typed
206 /// elements manipulated together. Structured can optionally be packed, meaning
207 /// that their elements immediately follow each other in memory without
208 /// accounting for potential alignment.
209 ///
210 /// Structure types can be identified (named) or literal. Literal structures
211 /// are uniquely represented by the list of types they contain and packedness.
212 /// Literal structure types are immutable after construction.
213 ///
214 /// Identified structures are uniquely represented by their name, a string. They
215 /// have a mutable component, consisting of the list of types they contain,
216 /// the packedness and the opacity bits. Identified structs can be created
217 /// without providing the lists of element types, making them suitable to
218 /// represent recursive, i.e. self-referring, structures. Identified structs
219 /// without body are considered opaque. For such structs, one can set the body.
220 /// Identified structs can be created as intentionally-opaque, implying that the
221 /// caller does not intend to ever set the body (e.g. forward-declarations of
222 /// structs from another module) and wants to disallow further modification of
223 /// the body. For intentionally-opaque structs or non-opaque structs with the
224 /// body, one is not allowed to set another body (however, one can set exactly
225 /// the same body).
226 ///
227 /// Note that the packedness of the struct takes place in uniquing of literal
228 /// structs, but does not in uniquing of identified structs.
229 class LLVMStructType : public Type::TypeBase<LLVMStructType, Type,
230                                              detail::LLVMStructTypeStorage> {
231 public:
232   /// Inherit base constructors.
233   using Base::Base;
234 
235   /// Checks if the given type can be contained in a structure type.
236   static bool isValidElementType(Type type);
237 
238   /// Gets or creates an identified struct with the given name in the provided
239   /// context. Note that unlike llvm::StructType::create, this function will
240   /// _NOT_ rename a struct in case a struct with the same name already exists
241   /// in the context. Instead, it will just return the existing struct,
242   /// similarly to the rest of MLIR type ::get methods.
243   static LLVMStructType getIdentified(MLIRContext *context, StringRef name);
244   static LLVMStructType
245   getIdentifiedChecked(function_ref<InFlightDiagnostic()> emitError,
246                        MLIRContext *context, StringRef name);
247 
248   /// Gets a new identified struct with the given body. The body _cannot_ be
249   /// changed later. If a struct with the given name already exists, renames
250   /// the struct by appending a `.` followed by a number to the name. Renaming
251   /// happens even if the existing struct has the same body.
252   static LLVMStructType getNewIdentified(MLIRContext *context, StringRef name,
253                                          ArrayRef<Type> elements,
254                                          bool isPacked = false);
255 
256   /// Gets or creates a literal struct with the given body in the provided
257   /// context.
258   static LLVMStructType getLiteral(MLIRContext *context, ArrayRef<Type> types,
259                                    bool isPacked = false);
260   static LLVMStructType
261   getLiteralChecked(function_ref<InFlightDiagnostic()> emitError,
262                     MLIRContext *context, ArrayRef<Type> types,
263                     bool isPacked = false);
264 
265   /// Gets or creates an intentionally-opaque identified struct. Such a struct
266   /// cannot have its body set. To create an opaque struct with a mutable body,
267   /// use `getIdentified`. Note that unlike llvm::StructType::create, this
268   /// function will _NOT_ rename a struct in case a struct with the same name
269   /// already exists in the context. Instead, it will just return the existing
270   /// struct, similarly to the rest of MLIR type ::get methods.
271   static LLVMStructType getOpaque(StringRef name, MLIRContext *context);
272   static LLVMStructType
273   getOpaqueChecked(function_ref<InFlightDiagnostic()> emitError,
274                    MLIRContext *context, StringRef name);
275 
276   /// Set the body of an identified struct. Returns failure if the body could
277   /// not be set, e.g. if the struct already has a body or if it was marked as
278   /// intentionally opaque. This might happen in a multi-threaded context when a
279   /// different thread modified the struct after it was created. Most callers
280   /// are likely to assert this always succeeds, but it is possible to implement
281   /// a local renaming scheme based on the result of this call.
282   LogicalResult setBody(ArrayRef<Type> types, bool isPacked);
283 
284   /// Checks if a struct is packed.
285   bool isPacked();
286 
287   /// Checks if a struct is identified.
288   bool isIdentified();
289 
290   /// Checks if a struct is opaque.
291   bool isOpaque();
292 
293   /// Checks if a struct is initialized.
294   bool isInitialized();
295 
296   /// Returns the name of an identified struct.
297   StringRef getName();
298 
299   /// Returns the list of element types contained in a non-opaque struct.
300   ArrayRef<Type> getBody();
301 
302   /// Verifies that the type about to be constructed is well-formed.
303   static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
304                               StringRef, bool);
305   static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
306                               ArrayRef<Type> types, bool);
307 };
308 
309 //===----------------------------------------------------------------------===//
310 // LLVMVectorType.
311 //===----------------------------------------------------------------------===//
312 
313 /// LLVM dialect vector type, represents a sequence of elements that can be
314 /// processed as one, typically in SIMD context. This is a base class for fixed
315 /// and scalable vectors.
316 class LLVMVectorType : public Type {
317 public:
318   /// Inherit base constructor.
319   using Type::Type;
320 
321   /// Support type casting functionality.
322   static bool classof(Type type);
323 
324   /// Checks if the given type can be used in a vector type.
325   static bool isValidElementType(Type type);
326 
327   /// Returns the element type of the vector.
328   Type getElementType();
329 
330   /// Returns the number of elements in the vector.
331   llvm::ElementCount getElementCount();
332 
333   /// Verifies that the type about to be constructed is well-formed.
334   static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
335                               Type elementType, unsigned numElements);
336 };
337 
338 //===----------------------------------------------------------------------===//
339 // LLVMFixedVectorType.
340 //===----------------------------------------------------------------------===//
341 
342 /// LLVM dialect fixed vector type, represents a sequence of elements of known
343 /// length that can be processed as one.
344 class LLVMFixedVectorType
345     : public Type::TypeBase<LLVMFixedVectorType, Type,
346                             detail::LLVMTypeAndSizeStorage> {
347 public:
348   /// Inherit base constructor.
349   using Base::Base;
350   using Base::getChecked;
351 
352   /// Gets or creates a fixed vector type containing `numElements` of
353   /// `elementType` in the same context as `elementType`.
354   static LLVMFixedVectorType get(Type elementType, unsigned numElements);
355   static LLVMFixedVectorType
356   getChecked(function_ref<InFlightDiagnostic()> emitError, Type elementType,
357              unsigned numElements);
358 
359   /// Checks if the given type can be used in a vector type. This type supports
360   /// only a subset of LLVM dialect types that don't have a built-in
361   /// counter-part, e.g., pointers.
362   static bool isValidElementType(Type type);
363 
364   /// Returns the element type of the vector.
365   Type getElementType();
366 
367   /// Returns the number of elements in the fixed vector.
368   unsigned getNumElements();
369 
370   /// Verifies that the type about to be constructed is well-formed.
371   static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
372                               Type elementType, unsigned numElements);
373 };
374 
375 //===----------------------------------------------------------------------===//
376 // LLVMScalableVectorType.
377 //===----------------------------------------------------------------------===//
378 
379 /// LLVM dialect scalable vector type, represents a sequence of elements of
380 /// unknown length that is known to be divisible by some constant. These
381 /// elements can be processed as one in SIMD context.
382 class LLVMScalableVectorType
383     : public Type::TypeBase<LLVMScalableVectorType, Type,
384                             detail::LLVMTypeAndSizeStorage> {
385 public:
386   /// Inherit base constructor.
387   using Base::Base;
388   using Base::getChecked;
389 
390   /// Gets or creates a scalable vector type containing a non-zero multiple of
391   /// `minNumElements` of `elementType` in the same context as `elementType`.
392   static LLVMScalableVectorType get(Type elementType, unsigned minNumElements);
393   static LLVMScalableVectorType
394   getChecked(function_ref<InFlightDiagnostic()> emitError, Type elementType,
395              unsigned minNumElements);
396 
397   /// Checks if the given type can be used in a vector type.
398   static bool isValidElementType(Type type);
399 
400   /// Returns the element type of the vector.
401   Type getElementType();
402 
403   /// Returns the scaling factor of the number of elements in the vector. The
404   /// vector contains at least the resulting number of elements, or any non-zero
405   /// multiple of this number.
406   unsigned getMinNumElements();
407 
408   /// Verifies that the type about to be constructed is well-formed.
409   static LogicalResult verify(function_ref<InFlightDiagnostic()> emitError,
410                               Type elementType, unsigned minNumElements);
411 };
412 
413 //===----------------------------------------------------------------------===//
414 // Printing and parsing.
415 //===----------------------------------------------------------------------===//
416 
417 namespace detail {
418 /// Parses an LLVM dialect type.
419 Type parseType(DialectAsmParser &parser);
420 
421 /// Prints an LLVM Dialect type.
422 void printType(Type type, DialectAsmPrinter &printer);
423 } // namespace detail
424 
425 //===----------------------------------------------------------------------===//
426 // Utility functions.
427 //===----------------------------------------------------------------------===//
428 
429 /// Returns `true` if the given type is compatible with the LLVM dialect.
430 bool isCompatibleType(Type type);
431 
432 /// Returns `true` if the given type is a floating-point type compatible with
433 /// the LLVM dialect.
434 bool isCompatibleFloatingPointType(Type type);
435 
436 /// Returns `true` if the given type is a vector type compatible with the LLVM
437 /// dialect. Compatible types include 1D built-in vector types of built-in
438 /// integers and floating-point values, LLVM dialect fixed vector types of LLVM
439 /// dialect pointers and LLVM dialect scalable vector types.
440 bool isCompatibleVectorType(Type type);
441 
442 /// Returns the element type of any vector type compatible with the LLVM
443 /// dialect.
444 Type getVectorElementType(Type type);
445 
446 /// Returns the element count of any LLVM-compatible vector type.
447 llvm::ElementCount getVectorNumElements(Type type);
448 
449 /// Creates an LLVM dialect-compatible type with the given element type and
450 /// length.
451 Type getFixedVectorType(Type elementType, unsigned numElements);
452 
453 /// Returns the size of the given primitive LLVM dialect-compatible type
454 /// (including vectors) in bits, for example, the size of i16 is 16 and
455 /// the size of vector<4xi16> is 64. Returns 0 for non-primitive
456 /// (aggregates such as struct) or types that don't have a size (such as void).
457 llvm::TypeSize getPrimitiveTypeSizeInBits(Type type);
458 
459 } // namespace LLVM
460 } // namespace mlir
461 
462 #endif // MLIR_DIALECT_LLVMIR_LLVMTYPES_H_
463