1//===- FIRTypes.td - FIR types -----------------------------*- 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// This file declares the FIR dialect types.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef FIR_DIALECT_FIR_TYPES
14#define FIR_DIALECT_FIR_TYPES
15
16include "flang/Optimizer/Dialect/FIRDialect.td"
17
18//===----------------------------------------------------------------------===//
19// FIR Types
20//===----------------------------------------------------------------------===//
21
22class FIR_Type<string name, string typeMnemonic> : TypeDef<fir_Dialect, name> {
23  let mnemonic = typeMnemonic;
24}
25
26def fir_Type : Type<CPred<"fir::isa_fir_or_std_type($_self)">,
27    "FIR dialect type">;
28
29def fir_BoxCharType : FIR_Type<"BoxChar", "boxchar"> {
30  let summary = "CHARACTER type descriptor.";
31
32  let description = [{
33    The type of a pair that describes a CHARACTER variable. Specifically, a
34    CHARACTER consists of a reference to a buffer (the string value) and a LEN
35    type parameter (the runtime length of the buffer).
36  }];
37
38  let parameters = (ins "KindTy":$kind);
39
40  let genAccessors = 1;
41
42  let extraClassDeclaration = [{
43    using KindTy = unsigned;
44
45    // a !fir.boxchar<k> always wraps a !fir.char<k, ?>
46    CharacterType getElementType(mlir::MLIRContext *context) const;
47
48    CharacterType getEleTy() const;
49  }];
50}
51
52def fir_BoxProcType : FIR_Type<"BoxProc", "boxproc"> {
53  let summary = "";
54
55  let description = [{
56    The type of a pair that describes a PROCEDURE reference. Pointers to
57    internal procedures must carry an additional reference to the host's
58    variables that are referenced.
59  }];
60
61  let parameters = (ins "mlir::Type":$eleTy);
62
63  let genVerifyDecl = 1;
64}
65
66def fir_BoxType : FIR_Type<"Box", "box"> {
67  let summary = "The type of a Fortran descriptor";
68
69  let description = [{
70    Descriptors are tuples of information that describe an entity being passed
71    from a calling context. This information might include (but is not limited
72    to) whether the entity is an array, its size, or what type it has.
73  }];
74
75  let parameters = (ins "mlir::Type":$eleTy, "mlir::AffineMapAttr":$map);
76
77  let skipDefaultBuilders = 1;
78
79  let builders = [
80    TypeBuilderWithInferredContext<(ins
81        "mlir::Type":$eleTy,
82        CArg<"mlir::AffineMapAttr", "{}">:$map), [{
83      return Base::get(eleTy.getContext(), eleTy, map);
84    }]>,
85  ];
86
87  let extraClassDeclaration = [{
88    mlir::Type getElementType() const { return getEleTy(); }
89    mlir::AffineMapAttr getLayoutMap() const { return getMap(); }
90  }];
91
92  let genVerifyDecl = 1;
93}
94
95def fir_CharacterType : FIR_Type<"Character", "char"> {
96  let summary = "FIR character type";
97
98  let description = [{
99    Model of the Fortran CHARACTER intrinsic type, including the KIND type
100    parameter. The model optionally includes a LEN type parameter. A
101    CharacterType is thus the type of both a single character value and a
102    character with a LEN parameter.
103  }];
104
105  let parameters = (ins "KindTy":$FKind, "CharacterType::LenType":$len);
106
107  let extraClassDeclaration = [{
108    using KindTy = unsigned;
109    using LenType = std::int64_t;
110
111    /// Return unknown length Character type. e.g., CHARACTER(LEN=n).
112    static CharacterType getUnknownLen(mlir::MLIRContext *ctxt, KindTy kind) {
113      return get(ctxt, kind, unknownLen());
114    }
115
116    /// Return length 1 Character type. e.g., CHARACTER(LEN=1).
117    static CharacterType getSingleton(mlir::MLIRContext *ctxt, KindTy kind) {
118      return get(ctxt, kind, singleton());
119    }
120
121    /// Character is a singleton and has a LEN of 1.
122    static constexpr LenType singleton() { return 1; }
123
124    /// Character has a LEN value which is not a compile-time known constant.
125    static constexpr LenType unknownLen() { return -1; }
126
127    /// Character LEN is a runtime value.
128    bool hasDynamicLen() { return getLen() == unknownLen(); }
129
130    /// Character LEN is a compile-time cpnstant value.
131    bool hasConstantLen() { return !hasDynamicLen(); }
132  }];
133}
134
135def fir_ComplexType : FIR_Type<"Complex", "complex"> {
136  let summary = "Complex type";
137
138  let description = [{
139    Model of a Fortran COMPLEX intrinsic type, including the KIND type
140    parameter. COMPLEX is a floating point type with a real and imaginary
141    member.
142  }];
143
144  let parameters = (ins "KindTy":$fKind);
145
146  let extraClassDeclaration = [{
147    using KindTy = unsigned;
148
149    mlir::Type getElementType() const;
150  }];
151}
152
153def fir_FieldType : FIR_Type<"Field", "field"> {
154  let summary = "A field (in a RecordType) argument's type";
155
156  let description = [{
157    The type of a field name. Implementations may defer the layout of a Fortran
158    derived type until runtime. This implies that the runtime must be able to
159    determine the offset of fields within the entity.
160  }];
161}
162
163def fir_HeapType : FIR_Type<"Heap", "heap"> {
164  let summary = "Reference to an ALLOCATABLE attribute type";
165
166  let description = [{
167    The type of a heap pointer. Fortran entities with the ALLOCATABLE attribute
168    may be allocated on the heap at runtime. These pointers are explicitly
169    distinguished to disallow the composition of multiple levels of
170    indirection. For example, an ALLOCATABLE POINTER is invalid.
171  }];
172
173  let parameters = (ins "mlir::Type":$eleTy);
174
175  let genVerifyDecl = 1;
176
177  let skipDefaultBuilders = 1;
178
179  let builders = [
180    TypeBuilderWithInferredContext<(ins "mlir::Type":$elementType), [{
181      assert(singleIndirectionLevel(elementType) && "invalid element type");
182      return Base::get(elementType.getContext(), elementType);
183    }]>,
184  ];
185}
186
187def fir_IntegerType : FIR_Type<"Integer", "int"> {
188  let summary = "FIR integer type";
189
190  let description = [{
191    Model of a Fortran INTEGER intrinsic type, including the KIND type
192    parameter.
193  }];
194
195  let parameters = (ins "KindTy":$fKind);
196
197  let extraClassDeclaration = [{
198    using KindTy = unsigned;
199  }];
200}
201
202def fir_LenType : FIR_Type<"Len", "len"> {
203  let summary = "A LEN parameter (in a RecordType) argument's type";
204
205  let description = [{
206    The type of a LEN parameter name. Implementations may defer the layout of a
207    Fortran derived type until runtime. This implies that the runtime must be
208    able to determine the offset of LEN type parameters related to an entity.
209  }];
210}
211
212def fir_LogicalType : FIR_Type<"Logical", "logical"> {
213  let summary = "FIR logical type";
214
215  let description = [{
216    Model of a Fortran LOGICAL intrinsic type, including the KIND type
217    parameter.
218  }];
219
220  let parameters = (ins "KindTy":$fKind);
221
222  let extraClassDeclaration = [{
223    using KindTy = unsigned;
224  }];
225}
226
227def fir_PointerType : FIR_Type<"Pointer", "ptr"> {
228  let summary = "Reference to a POINTER attribute type";
229
230  let description = [{
231    The type of entities with the POINTER attribute.  These pointers are
232    explicitly distinguished to disallow the composition of multiple levels of
233    indirection. For example, an ALLOCATABLE POINTER is invalid.
234  }];
235
236  let parameters = (ins "mlir::Type":$eleTy);
237
238  let genVerifyDecl = 1;
239
240  let skipDefaultBuilders = 1;
241
242  let builders = [
243    TypeBuilderWithInferredContext<(ins "mlir::Type":$elementType), [{
244      assert(singleIndirectionLevel(elementType) && "invalid element type");
245      return Base::get(elementType.getContext(), elementType);
246    }]>,
247  ];
248
249  let extraClassDeclaration = [{
250    mlir::Type getElementType() const { return getEleTy(); }
251  }];
252}
253
254def fir_RealType : FIR_Type<"Real", "real"> {
255  let summary = "FIR real type";
256
257  let description = [{
258    Model of a Fortran REAL (and DOUBLE PRECISION) intrinsic type, including the
259    KIND type parameter.
260  }];
261
262  let parameters = (ins "KindTy":$fKind);
263
264  let extraClassDeclaration = [{
265    using KindTy = unsigned;
266  }];
267
268  let genVerifyDecl = 1;
269}
270
271def fir_RecordType : FIR_Type<"Record", "type"> {
272  let summary = "FIR derived type";
273
274  let description = [{
275    Model of Fortran's derived type, TYPE. The name of the TYPE includes any
276    KIND type parameters. The record includes runtime slots for LEN type
277    parameters and for data components.
278  }];
279
280  let parameters = (ins StringRefParameter<"name">:$name);
281
282  let genVerifyDecl = 1;
283  let genStorageClass = 0;
284
285  let extraClassDeclaration = [{
286    using TypePair = std::pair<std::string, mlir::Type>;
287    using TypeList = std::vector<TypePair>;
288    TypeList getTypeList() const;
289    TypeList getLenParamList() const;
290
291    mlir::Type getType(llvm::StringRef ident);
292    // Returns the index of the field \p ident in the type list.
293    // Returns maximum unsigned if ident is not a field of this RecordType.
294    unsigned getFieldIndex(llvm::StringRef ident);
295    mlir::Type getType(unsigned index) {
296      assert(index < getNumFields());
297      return getTypeList()[index].second;
298    }
299    unsigned getNumFields() { return getTypeList().size(); }
300    unsigned getNumLenParams() { return getLenParamList().size(); }
301
302    void finalize(llvm::ArrayRef<TypePair> lenPList,
303                  llvm::ArrayRef<TypePair> typeList);
304
305    detail::RecordTypeStorage const *uniqueKey() const;
306  }];
307}
308
309def fir_ReferenceType : FIR_Type<"Reference", "ref"> {
310  let summary = "Reference to an entity type";
311
312  let description = [{
313    The type of a reference to an entity in memory.
314  }];
315
316  let parameters = (ins "mlir::Type":$eleTy);
317
318  let skipDefaultBuilders = 1;
319
320  let builders = [
321    TypeBuilderWithInferredContext<(ins "mlir::Type":$elementType), [{
322      return Base::get(elementType.getContext(), elementType);
323    }]>,
324  ];
325
326  let extraClassDeclaration = [{
327    mlir::Type getElementType() const { return getEleTy(); }
328  }];
329
330  let genVerifyDecl = 1;
331}
332
333def fir_ShapeType : FIR_Type<"Shape", "shape"> {
334  let summary = "shape of a multidimensional array object";
335
336  let description = [{
337    Type of a vector of runtime values that define the shape of a
338    multidimensional array object. The vector is the extents of each array
339    dimension. The rank of a ShapeType must be at least 1.
340  }];
341
342  let parameters = (ins "unsigned":$rank);
343}
344
345def fir_ShapeShiftType : FIR_Type<"ShapeShift", "shapeshift"> {
346  let summary = "shape and origin of a multidimensional array object";
347
348  let description = [{
349    Type of a vector of runtime values that define the shape and the origin of a
350    multidimensional array object. The vector is of pairs, origin offset and
351    extent, of each array dimension. The rank of a ShapeShiftType must be at
352    least 1.
353  }];
354
355  let parameters = (ins "unsigned":$rank);
356}
357
358def fir_ShiftType : FIR_Type<"Shift", "shift"> {
359  let summary = "lower bounds of a multidimensional array object";
360
361  let description = [{
362    Type of a vector of runtime values that define the lower bounds of a
363    multidimensional array object. The vector is the lower bounds of each array
364    dimension. The rank of a ShiftType must be at least 1.
365  }];
366
367  let parameters = (ins "unsigned":$rank);
368
369  let extraClassDeclaration = [{
370    using KindTy = unsigned;
371
372    // a !fir.boxchar<k> always wraps a !fir.char<k, ?>
373    CharacterType getElementType(mlir::MLIRContext *context) const;
374
375    CharacterType getEleTy() const;
376  }];
377}
378
379def fir_SequenceType : FIR_Type<"Sequence", "array"> {
380  let summary = "FIR array type";
381
382  let description = [{
383    A sequence type is a multi-dimensional array of values. The sequence type
384    may have an unknown number of dimensions or the extent of dimensions may be
385    unknown. A sequence type models a Fortran array entity, giving it a type in
386    FIR. A sequence type is assumed to be stored in a column-major order, which
387    differs from LLVM IR and other dialects of MLIR.
388  }];
389
390  let parameters = (ins
391    ArrayRefParameter<"int64_t", "Sequence shape">:$shape,
392    "mlir::Type":$eleTy,
393    "mlir::AffineMapAttr":$layoutMap
394  );
395
396  let genVerifyDecl = 1;
397
398  let builders = [
399    TypeBuilderWithInferredContext<(ins
400        "llvm::ArrayRef<int64_t>":$shape,
401        "mlir::Type":$eleTy), [{
402      return get(eleTy.getContext(), shape, eleTy, {});
403    }]>,
404  ];
405
406  let extraClassDeclaration = [{
407    using Extent = int64_t;
408    using Shape = llvm::SmallVector<Extent, 8>;
409    using ShapeRef = llvm::ArrayRef<int64_t>;
410    unsigned getConstantRows() const;
411
412    // The number of dimensions of the sequence
413    unsigned getDimension() const { return getShape().size(); }
414
415    // Is the interior of the sequence constant? Check if the array is
416    // one of constant shape (`array<C...xCxT>`), unknown shape
417    // (`array<*xT>`), or rows with shape and ending with column(s) of
418    // unknown extent (`array<C...xCx?...x?xT>`).
419    bool hasConstantInterior() const;
420
421    // Is the shape of the sequence constant?
422    bool hasConstantShape() const { return getConstantRows() == getDimension(); }
423
424    // Does the sequence have unknown shape? (`array<* x T>`)
425    bool hasUnknownShape() const { return getShape().empty(); }
426
427    // The value `-1` represents an unknown extent for a dimension
428    static constexpr Extent getUnknownExtent() { return -1; }
429  }];
430}
431
432def fir_SliceType : FIR_Type<"Slice", "slice"> {
433  let summary = "FIR slice";
434
435  let description = [{
436    Type of a vector that represents an array slice operation on an array.
437    Fortran slices are triples of lower bound, upper bound, and stride. The rank
438    of a SliceType must be at least 1.
439  }];
440
441  let parameters = (ins "unsigned":$rank);
442}
443
444def fir_TypeDescType : FIR_Type<"TypeDesc", "tdesc"> {
445  let summary = "FIR Type descriptor type";
446
447  let description = [{
448    The type of a type descriptor object. The runtime may generate type
449    descriptor objects to determine the type of an entity at runtime, etc.
450  }];
451
452  let parameters = (ins "mlir::Type":$ofTy);
453
454  let genVerifyDecl = 1;
455
456  let skipDefaultBuilders = 1;
457
458  let builders = [
459    TypeBuilderWithInferredContext<(ins "mlir::Type":$elementType), [{
460      return Base::get(elementType.getContext(), elementType);
461    }]>,
462  ];
463}
464
465def fir_VectorType : FIR_Type<"Vector", "vector"> {
466  let summary = "FIR vector type";
467
468  let description = [{
469    Replacement for the builtin vector type.
470    The FIR vector type is always rank one. It's size is always a constant.
471    A vector's element type must be real or integer.
472  }];
473
474  let parameters = (ins "uint64_t":$len, "mlir::Type":$eleTy);
475
476  let genVerifyDecl = 1;
477
478  let extraClassDeclaration = [{
479    static bool isValidElementType(mlir::Type t);
480  }];
481
482  let skipDefaultBuilders = 1;
483
484  let builders = [
485    TypeBuilderWithInferredContext<(ins
486        "uint64_t":$len,
487        "mlir::Type":$eleTy), [{
488      return Base::get(eleTy.getContext(), len, eleTy);
489    }]>,
490  ];
491}
492
493def fir_VoidType : FIR_Type<"Void", "void"> {
494  let genStorageClass = 0;
495}
496
497// Generalized FIR and standard dialect types representing intrinsic types
498def AnyIntegerLike : TypeConstraint<Or<[SignlessIntegerLike.predicate,
499    AnySignedInteger.predicate, fir_IntegerType.predicate]>, "any integer">;
500def AnyLogicalLike : TypeConstraint<Or<[BoolLike.predicate,
501    fir_LogicalType.predicate]>, "any logical">;
502def AnyRealLike : TypeConstraint<Or<[FloatLike.predicate,
503    fir_RealType.predicate]>, "any real">;
504def AnyIntegerType : Type<AnyIntegerLike.predicate, "any integer">;
505
506// Composable types
507def AnyCompositeLike : TypeConstraint<Or<[fir_RecordType.predicate,
508    fir_SequenceType.predicate, fir_ComplexType.predicate,
509    fir_VectorType.predicate, IsTupleTypePred, fir_CharacterType.predicate]>,
510    "any composite">;
511
512// Reference types
513def AnyReferenceLike : TypeConstraint<Or<[fir_ReferenceType.predicate,
514    fir_HeapType.predicate, fir_PointerType.predicate]>, "any reference">;
515
516def AnyBoxLike : TypeConstraint<Or<[fir_BoxType.predicate,
517    fir_BoxCharType.predicate, fir_BoxProcType.predicate]>, "any box">;
518
519def AnyRefOrBoxLike : TypeConstraint<Or<[AnyReferenceLike.predicate,
520    AnyBoxLike.predicate]>,
521    "any reference or box like">;
522def AnyRefOrBox : TypeConstraint<Or<[fir_ReferenceType.predicate,
523    fir_HeapType.predicate, fir_PointerType.predicate, fir_BoxType.predicate]>,
524    "any reference or box">;
525
526def AnyShapeLike : TypeConstraint<Or<[fir_ShapeType.predicate,
527    fir_ShapeShiftType.predicate]>, "any legal shape type">;
528def AnyShapeType : Type<AnyShapeLike.predicate, "any legal shape type">;
529def AnyShapeOrShiftLike : TypeConstraint<Or<[fir_ShapeType.predicate,
530    fir_ShapeShiftType.predicate, fir_ShiftType.predicate]>,
531    "any legal shape or shift type">;
532def AnyShapeOrShiftType : Type<AnyShapeOrShiftLike.predicate,
533    "any legal shape or shift type">;
534
535def AnyEmboxLike : TypeConstraint<Or<[AnySignlessInteger.predicate,
536    Index.predicate, fir_IntegerType.predicate]>,
537    "any legal embox argument type">;
538def AnyEmboxArg : Type<AnyEmboxLike.predicate, "embox argument type">;
539
540def AnyComponentLike : TypeConstraint<Or<[AnySignlessInteger.predicate,
541    Index.predicate, fir_IntegerType.predicate, fir_FieldType.predicate]>,
542    "any coordinate index">;
543def AnyComponentType : Type<AnyComponentLike.predicate, "coordinate type">;
544
545def AnyCoordinateLike : TypeConstraint<Or<[AnySignlessInteger.predicate,
546    Index.predicate, fir_IntegerType.predicate, fir_FieldType.predicate,
547    fir_LenType.predicate]>, "any coordinate index">;
548def AnyCoordinateType : Type<AnyCoordinateLike.predicate, "coordinate type">;
549
550// The legal types of global symbols
551def AnyAddressableLike : TypeConstraint<Or<[fir_ReferenceType.predicate,
552    FunctionType.predicate]>, "any addressable">;
553
554#endif // FIR_DIALECT_FIR_TYPES
555