xref: /llvm-project/mlir/include/mlir/Dialect/LLVMIR/LLVMTypes.td (revision 332719561000dcac94384234ace1fa959362ad8e)
1//===-- LLVMOps.td - LLVM IR dialect op definition file ----*- tablegen -*-===//
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 LLVMTYPES_TD
10#define LLVMTYPES_TD
11
12include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
13include "mlir/IR/AttrTypeBase.td"
14include "mlir/Interfaces/DataLayoutInterfaces.td"
15include "mlir/Interfaces/MemorySlotInterfaces.td"
16
17/// Base class for all LLVM dialect types.
18class LLVMType<string typeName, string typeMnemonic, list<Trait> traits = []>
19    : TypeDef<LLVM_Dialect, typeName, traits> {
20  let mnemonic = typeMnemonic;
21}
22
23//===----------------------------------------------------------------------===//
24// LLVMArrayType
25//===----------------------------------------------------------------------===//
26
27def LLVMArrayType : LLVMType<"LLVMArray", "array", [
28    DeclareTypeInterfaceMethods<DataLayoutTypeInterface, ["getTypeSize"]>,
29    DeclareTypeInterfaceMethods<DestructurableTypeInterface>]> {
30  let summary = "LLVM array type";
31  let description = [{
32    The `!llvm.array` type represents a fixed-size array of element types.
33    It is an aggregate type representing consecutive elements in memory,
34    parameterized by the number of elements and the element type.
35
36    Example:
37
38    ```mlir
39    !llvm.array<4 x i32>
40    ```
41  }];
42
43  let parameters = (ins "Type":$elementType, "uint64_t":$numElements);
44  let assemblyFormat = [{
45    `<` $numElements `x` custom<PrettyLLVMType>($elementType) `>`
46  }];
47
48  let genVerifyDecl = 1;
49
50  let builders = [
51    TypeBuilderWithInferredContext<(ins "Type":$elementType,
52                                        "uint64_t":$numElements)>
53  ];
54
55  let extraClassDeclaration = [{
56    /// Checks if the given type can be used inside an array type.
57    static bool isValidElementType(Type type);
58  }];
59}
60
61//===----------------------------------------------------------------------===//
62// LLVMFunctionType
63//===----------------------------------------------------------------------===//
64
65def LLVMFunctionType : LLVMType<"LLVMFunction", "func"> {
66  let summary = "LLVM function type";
67  let description = [{
68    The `!llvm.func` is a function type. It consists of a single return type
69    (unlike MLIR which can have multiple), a list of parameter types and can
70    optionally be variadic.
71
72    Example:
73
74    ```mlir
75    !llvm.func<i32 (i32)>
76    ```
77  }];
78
79  let parameters = (ins "Type":$returnType, ArrayRefParameter<"Type">:$params,
80                        "bool":$varArg);
81  let assemblyFormat = [{
82    `<` custom<PrettyLLVMType>($returnType) ` ` `(`
83    custom<FunctionTypes>($params, $varArg) `>`
84  }];
85
86  let genVerifyDecl = 1;
87
88  let builders = [
89    TypeBuilderWithInferredContext<(ins
90      "Type":$result, "ArrayRef<Type>":$arguments,
91      CArg<"bool", "false">:$isVarArg)>
92  ];
93
94  let extraClassDeclaration = [{
95    /// Checks if the given type can be used an argument in a function type.
96    static bool isValidArgumentType(Type type);
97
98    /// Checks if the given type can be used as a result in a function type.
99    static bool isValidResultType(Type type);
100
101    /// Returns whether the function is variadic.
102    bool isVarArg() const { return getVarArg(); }
103
104    /// Returns a clone of this function type with the given argument
105    /// and result types.
106    LLVMFunctionType clone(TypeRange inputs, TypeRange results) const;
107
108    /// Returns the result type of the function as an ArrayRef, enabling better
109    /// integration with generic MLIR utilities.
110    ArrayRef<Type> getReturnTypes() const;
111
112    /// Returns the number of arguments to the function.
113    unsigned getNumParams() const { return getParams().size(); }
114
115    /// Returns `i`-th argument of the function. Asserts on out-of-bounds.
116    Type getParamType(unsigned i) { return getParams()[i]; }
117  }];
118}
119
120//===----------------------------------------------------------------------===//
121// LLVMStructType
122//===----------------------------------------------------------------------===//
123
124def LLVMStructType : LLVMType<"LLVMStruct", "struct", [
125  MutableType,
126  DeclareTypeInterfaceMethods<DataLayoutTypeInterface,
127    ["areCompatible", "verifyEntries"]>,
128  DeclareTypeInterfaceMethods<DestructurableTypeInterface,
129    ["getSubelementIndexMap", "getTypeAtIndex"]>
130]> {
131  let summary = "LLVM struct type";
132
133  let description = [{
134    LLVM dialect structure type representing a collection of different-typed
135    elements manipulated together. Struct types can optionally be packed, meaning
136    that their elements immediately follow each other in memory without
137    accounting for potential alignment.
138
139    Structure types can be identified (named) or literal. Literal structures
140    are uniquely represented by the list of types they contain and packedness.
141    Literal structure types are immutable after construction.
142
143    Identified structures are uniquely represented by their name, a string. They
144    have a mutable component, consisting of the list of types they contain,
145    the packedness and the opacity bits. Identified structs can be created
146    without providing the lists of element types, making them suitable to
147    represent recursive, i.e. self-referring, structures. Identified structs
148    without body are considered opaque. For such structs, one can set the body.
149    Identified structs can be created as intentionally-opaque, implying that the
150    caller does not intend to ever set the body (e.g. forward-declarations of
151    structs from another module) and wants to disallow further modification of
152    the body. For intentionally-opaque structs or non-opaque structs with the
153    body, one is not allowed to set another body (however, one can set exactly
154    the same body).
155
156    Note that the packedness of the struct takes place in uniquing of literal
157    structs, but does not in uniquing of identified structs.
158  }];
159
160  // Specify parameters for which TableGen can generate convenient getters for
161  // us.
162  // TODO: Other parameters such as 'packed' or 'opaque' could be added in the
163  //       future iff they generate getters prefixed with 'is', instead of
164  //       'get'. Until then there are no advantages in doing so.
165  let parameters = (ins
166    StringRefParameter<"struct name", [{""}]>:$name,
167    OptionalArrayRefParameter<"mlir::Type">:$body
168  );
169
170  // A custom storage class defined in C++ is required to implement mutability.
171  let storageClass = "LLVMStructTypeStorage";
172  let genStorageClass = 0;
173
174  // We want users to use the more aptly named custom builders below.
175  let skipDefaultBuilders = 1;
176
177  let extraClassDeclaration = [{
178    /// Checks if the given type can be contained in a structure type.
179    static bool isValidElementType(Type type);
180
181    /// Gets or creates an identified struct with the given name in the provided
182    /// context. Note that unlike llvm::StructType::create, this function will
183    /// _NOT_ rename a struct in case a struct with the same name already exists
184    /// in the context. Instead, it will just return the existing struct,
185    /// similarly to the rest of MLIR type ::get methods.
186    static LLVMStructType getIdentified(MLIRContext *context, StringRef name);
187    static LLVMStructType
188    getIdentifiedChecked(function_ref<InFlightDiagnostic()> emitError,
189                         MLIRContext *context, StringRef name);
190
191    /// Gets a new identified struct with the given body. The body _cannot_ be
192    /// changed later. If a struct with the given name already exists, renames
193    /// the struct by appending a `.` followed by a number to the name. Renaming
194    /// happens even if the existing struct has the same body.
195    static LLVMStructType getNewIdentified(MLIRContext *context, StringRef name,
196                                           ArrayRef<Type> elements,
197                                           bool isPacked = false);
198
199    /// Gets or creates a literal struct with the given body in the provided
200    /// context.
201    static LLVMStructType getLiteral(MLIRContext *context, ArrayRef<Type> types,
202                                     bool isPacked = false);
203
204    static LLVMStructType
205    getLiteralChecked(function_ref<InFlightDiagnostic()> emitError,
206                      MLIRContext *context, ArrayRef<Type> types,
207                      bool isPacked = false);
208
209    /// Gets or creates an intentionally-opaque identified struct. Such a struct
210    /// cannot have its body set.
211    /// Note that unlike llvm::StructType::create, this function will _NOT_
212    /// rename a struct in case a struct with the same name
213    /// already exists in the context. Instead, it will just return the existing
214    /// struct, similarly to the rest of MLIR type ::get methods.
215    static LLVMStructType getOpaque(StringRef name, MLIRContext *context);
216
217    static LLVMStructType
218    getOpaqueChecked(function_ref<InFlightDiagnostic()> emitError,
219                     MLIRContext *context, StringRef name);
220
221    /// Set the body of an identified struct. Returns failure if the body could
222    /// not be set, e.g. if the struct already has a body or if it was marked as
223    /// intentionally opaque. This might happen in a multi-threaded context when a
224    /// different thread modified the struct after it was created. Most callers
225    /// are likely to assert this always succeeds, but it is possible to implement
226    /// a local renaming scheme based on the result of this call.
227    LogicalResult setBody(ArrayRef<Type> types, bool isPacked);
228
229    /// Checks if a struct is packed.
230    bool isPacked() const;
231
232    /// Checks if a struct is identified.
233    bool isIdentified() const;
234
235    /// Checks if a struct is opaque.
236    bool isOpaque() const;
237
238    /// Checks if a struct is initialized.
239    bool isInitialized();
240
241    /// Verifies that the type about to be constructed is well-formed.
242    static LogicalResult
243    verifyInvariants(function_ref<InFlightDiagnostic()> emitError, StringRef,
244                     bool);
245    static LogicalResult
246    verifyInvariants(function_ref<InFlightDiagnostic()> emitError,
247                     ArrayRef<Type> types, bool);
248    using Base::verifyInvariants;
249  }];
250
251  let hasCustomAssemblyFormat = 1;
252}
253
254//===----------------------------------------------------------------------===//
255// LLVMPointerType
256//===----------------------------------------------------------------------===//
257
258def LLVMPointerType : LLVMType<"LLVMPointer", "ptr", [
259    DeclareTypeInterfaceMethods<DataLayoutTypeInterface, [
260      "getIndexBitwidth", "areCompatible", "verifyEntries"]>]> {
261  let summary = "LLVM pointer type";
262  let description = [{
263    The `!llvm.ptr` type is an LLVM pointer type. This type typically represents
264    a reference to an object in memory. Pointers are optionally parameterized
265    by the address space.
266
267    Example:
268
269    ```mlir
270    !llvm.ptr
271    ```
272  }];
273
274  let parameters = (ins DefaultValuedParameter<"unsigned", "0">:$addressSpace);
275  let assemblyFormat = [{
276    (`<` $addressSpace^ `>`)?
277  }];
278
279  let skipDefaultBuilders = 1;
280  let builders = [
281    TypeBuilder<(ins CArg<"unsigned", "0">:$addressSpace), [{
282      return $_get($_ctxt, addressSpace);
283    }]>
284  ];
285}
286
287//===----------------------------------------------------------------------===//
288// LLVMFixedVectorType
289//===----------------------------------------------------------------------===//
290
291def LLVMFixedVectorType : LLVMType<"LLVMFixedVector", "vec"> {
292  let summary = "LLVM fixed vector type";
293  let description = [{
294    LLVM dialect scalable vector type, represents a sequence of elements of
295    unknown length that is known to be divisible by some constant. These
296    elements can be processed as one in SIMD context.
297  }];
298
299  let typeName = "llvm.fixed_vec";
300
301  let parameters = (ins "Type":$elementType, "unsigned":$numElements);
302  let assemblyFormat = [{
303    `<` $numElements `x` custom<PrettyLLVMType>($elementType) `>`
304  }];
305
306  let genVerifyDecl = 1;
307
308  let builders = [
309    TypeBuilderWithInferredContext<(ins "Type":$elementType,
310                                        "unsigned":$numElements)>
311  ];
312
313  let extraClassDeclaration = [{
314    /// Checks if the given type can be used in a vector type.
315    static bool isValidElementType(Type type);
316  }];
317}
318
319//===----------------------------------------------------------------------===//
320// LLVMScalableVectorType
321//===----------------------------------------------------------------------===//
322
323def LLVMScalableVectorType : LLVMType<"LLVMScalableVector", "vec"> {
324  let summary = "LLVM scalable vector type";
325  let description = [{
326    LLVM dialect scalable vector type, represents a sequence of elements of
327    unknown length that is known to be divisible by some constant. These
328    elements can be processed as one in SIMD context.
329  }];
330
331  let typeName = "llvm.scalable_vec";
332
333  let parameters = (ins "Type":$elementType, "unsigned":$minNumElements);
334  let assemblyFormat = [{
335    `<` `?` `x` $minNumElements `x` ` ` custom<PrettyLLVMType>($elementType) `>`
336  }];
337
338  let genVerifyDecl = 1;
339
340  let builders = [
341    TypeBuilderWithInferredContext<(ins "Type":$elementType,
342                                        "unsigned":$minNumElements)>
343  ];
344
345  let extraClassDeclaration = [{
346    /// Checks if the given type can be used in a vector type.
347    static bool isValidElementType(Type type);
348  }];
349}
350
351//===----------------------------------------------------------------------===//
352// LLVMTargetExtType
353//===----------------------------------------------------------------------===//
354
355def LLVMTargetExtType : LLVMType<"LLVMTargetExt", "target"> {
356  let summary = "LLVM target-specific extension type";
357  let description = [{
358    LLVM dialect target extension type, which are generally unintrospectable
359    from target-independent optimizations.
360
361    Target extension types have a string name, and optionally have type and/or
362    integer parameters. The exact meaning of any parameters is dependent on the
363    target.
364  }];
365
366  let parameters = (ins StringRefParameter<>:$extTypeName,
367                        OptionalArrayRefParameter<"Type">:$typeParams,
368                        OptionalArrayRefParameter<"unsigned int">:$intParams);
369
370  let assemblyFormat = [{
371    `<` $extTypeName (`,` custom<ExtTypeParams>($typeParams, $intParams)^ )? `>`
372  }];
373
374  let extraClassDeclaration = [{
375    enum Property {
376      /// zeroinitializer is valid for this target extension type.
377      HasZeroInit = 1U << 0,
378      /// This type may be used as the value type of a global variable.
379      CanBeGlobal = 1U << 1,
380    };
381
382    bool hasProperty(Property Prop) const;
383    bool supportsMemOps() const;
384  }];
385}
386
387//===----------------------------------------------------------------------===//
388// LLVMX86AMXType
389//===----------------------------------------------------------------------===//
390
391def LLVMX86AMXType : LLVMType<"LLVMX86AMX", "x86_amx"> {
392  let summary = "LLVM x86_amx type.";
393  let description = [{
394    The x86_amx type represents a value held in an AMX tile register on an x86
395    machine. Can only be used in AMX intrinsics calls.
396  }];
397}
398
399#endif // LLVMTYPES_TD
400