FLANG
FIRType.h
1//===-- Optimizer/Dialect/FIRType.h -- FIR 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// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef FORTRAN_OPTIMIZER_DIALECT_FIRTYPE_H
14#define FORTRAN_OPTIMIZER_DIALECT_FIRTYPE_H
15
16#include "mlir/IR/BuiltinAttributes.h"
17#include "mlir/IR/BuiltinTypes.h"
18#include "mlir/Interfaces/DataLayoutInterfaces.h"
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/IR/Type.h"
21
22namespace fir {
23class FIROpsDialect;
24class KindMapping;
25using KindTy = unsigned;
26
27namespace detail {
28struct RecordTypeStorage;
29} // namespace detail
30
31} // namespace fir
32
33//===----------------------------------------------------------------------===//
34// BaseBoxType
35//===----------------------------------------------------------------------===//
36
37namespace fir {
38
40class BaseBoxType : public mlir::Type {
41public:
42 using mlir::Type::Type;
43
45 enum class Attribute { None, Allocatable, Pointer };
46
48 mlir::Type getEleTy() const;
49
51 mlir::Type unwrapInnerType() const;
52
54 bool isAssumedRank() const;
55
58 BaseBoxType getBoxTypeWithNewShape(mlir::Type shapeMold) const;
59 BaseBoxType getBoxTypeWithNewShape(int rank) const;
60
63
65 static bool classof(mlir::Type type);
66};
67
68} // namespace fir
69
70#define GET_TYPEDEF_CLASSES
71#include "flang/Optimizer/Dialect/FIROpsTypes.h.inc"
72
73namespace llvm {
74class raw_ostream;
75class StringRef;
76template <typename>
78class hash_code;
79} // namespace llvm
80
81namespace mlir {
82class DialectAsmParser;
83class DialectAsmPrinter;
84class ComplexType;
85class FloatType;
86class ValueRange;
87} // namespace mlir
88
89namespace fir {
90namespace detail {
91struct RecordTypeStorage;
92} // namespace detail
93
94// These isa_ routines follow the precedent of llvm::isa_or_null<>
95
97bool isa_fir_type(mlir::Type t);
98
100bool isa_std_type(mlir::Type t);
101
103bool isa_fir_or_std_type(mlir::Type t);
104
106inline bool isa_ref_type(mlir::Type t) {
107 return mlir::isa<fir::ReferenceType, fir::PointerType, fir::HeapType,
108 fir::LLVMPointerType>(t);
109}
110
112inline bool isa_box_type(mlir::Type t) {
113 return mlir::isa<fir::BaseBoxType, fir::BoxCharType, fir::BoxProcType>(t);
114}
115
119inline bool isa_passbyref_type(mlir::Type t) {
120 return mlir::isa<fir::ReferenceType, mlir::FunctionType>(t) ||
121 isa_box_type(t);
122}
123
127inline bool conformsWithPassByRef(mlir::Type t) {
128 return isa_ref_type(t) || isa_box_type(t) || mlir::isa<mlir::FunctionType>(t);
129}
130
132inline bool isa_derived(mlir::Type t) { return mlir::isa<fir::RecordType>(t); }
133
135inline bool isa_builtin_cptr_type(mlir::Type t) {
136 if (auto recTy = mlir::dyn_cast_or_null<fir::RecordType>(t))
137 return recTy.getName().ends_with("T__builtin_c_ptr") ||
138 recTy.getName().ends_with("T__builtin_c_funptr");
139 return false;
140}
141
142// Is `t` type(c_devptr)?
143inline bool isa_builtin_c_devptr_type(mlir::Type t) {
144 if (auto recTy = mlir::dyn_cast_or_null<fir::RecordType>(t))
145 return recTy.getName().ends_with("T__builtin_c_devptr");
146 return false;
147}
148
150inline bool isa_builtin_cdevptr_type(mlir::Type t) {
151 if (auto recTy = mlir::dyn_cast_or_null<fir::RecordType>(t))
152 return recTy.getName().ends_with("T__builtin_c_devptr");
153 return false;
154}
155
157inline bool isa_aggregate(mlir::Type t) {
158 return mlir::isa<SequenceType, mlir::TupleType>(t) || fir::isa_derived(t);
159}
160
163mlir::Type dyn_cast_ptrEleTy(mlir::Type t);
164
167mlir::Type dyn_cast_ptrOrBoxEleTy(mlir::Type t);
168
170inline bool isa_real(mlir::Type t) { return mlir::isa<mlir::FloatType>(t); }
171
173inline bool isa_integer(mlir::Type t) {
174 return mlir::isa<mlir::IndexType, mlir::IntegerType, fir::IntegerType>(t);
175}
176
178inline bool isa_vector(mlir::Type t) {
179 return mlir::isa<mlir::VectorType, fir::VectorType>(t);
180}
181
182mlir::Type parseFirType(FIROpsDialect *, mlir::DialectAsmParser &parser);
183
184void printFirType(FIROpsDialect *, mlir::Type ty, mlir::DialectAsmPrinter &p);
185
188void verifyIntegralType(mlir::Type type);
189
191inline bool isa_complex(mlir::Type t) {
192 return mlir::isa<mlir::ComplexType>(t) &&
193 mlir::isa<mlir::FloatType>(
194 mlir::cast<mlir::ComplexType>(t).getElementType());
195}
196
198inline bool isa_char(mlir::Type t) { return mlir::isa<fir::CharacterType>(t); }
199
202inline bool isa_trivial(mlir::Type t) {
203 return isa_integer(t) || isa_real(t) || isa_complex(t) || isa_vector(t) ||
204 mlir::isa<fir::LogicalType>(t);
205}
206
208inline bool isa_char_string(mlir::Type t) {
209 if (auto ct = mlir::dyn_cast_or_null<fir::CharacterType>(t))
210 return ct.getLen() != fir::CharacterType::singleton();
211 return false;
212}
213
219bool isa_unknown_size_box(mlir::Type t);
220
222inline bool characterWithDynamicLen(mlir::Type t) {
223 if (auto charTy = mlir::dyn_cast<fir::CharacterType>(t))
224 return charTy.hasDynamicLen();
225 return false;
226}
227
230inline bool sequenceWithNonConstantShape(fir::SequenceType seqTy) {
231 return seqTy.hasUnknownShape() || seqTy.hasDynamicExtents();
232}
233
235bool hasDynamicSize(mlir::Type t);
236
237inline unsigned getRankOfShapeType(mlir::Type t) {
238 if (auto shTy = mlir::dyn_cast<fir::ShapeType>(t))
239 return shTy.getRank();
240 if (auto shTy = mlir::dyn_cast<fir::ShapeShiftType>(t))
241 return shTy.getRank();
242 if (auto shTy = mlir::dyn_cast<fir::ShiftType>(t))
243 return shTy.getRank();
244 return 0;
245}
246
248inline mlir::Type boxMemRefType(fir::BaseBoxType t) {
249 auto eleTy = t.getEleTy();
250 if (!mlir::isa<fir::PointerType, fir::HeapType>(eleTy))
251 eleTy = fir::ReferenceType::get(t);
252 return eleTy;
253}
254
256inline mlir::Type unwrapSequenceType(mlir::Type t) {
257 if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(t))
258 return seqTy.getEleTy();
259 return t;
260}
261
263mlir::Type extractSequenceType(mlir::Type ty);
264
265inline mlir::Type unwrapRefType(mlir::Type t) {
266 if (auto eleTy = dyn_cast_ptrEleTy(t))
267 return eleTy;
268 return t;
269}
270
273inline mlir::Type unwrapPassByRefType(mlir::Type t) {
274 if (auto eleTy = dyn_cast_ptrOrBoxEleTy(t))
275 return eleTy;
276 return t;
277}
278
286mlir::Type unwrapSeqOrBoxedSeqType(mlir::Type ty);
287
291mlir::Type unwrapAllRefAndSeqType(mlir::Type ty);
292
295inline fir::SequenceType unwrapUntilSeqType(mlir::Type t) {
296 while (true) {
297 if (!t)
298 return {};
299 if (auto ty = dyn_cast_ptrOrBoxEleTy(t)) {
300 t = ty;
301 continue;
302 }
303 if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(t))
304 return seqTy;
305 return {};
306 }
307}
308
311inline fir::RecordType unwrapIfDerived(fir::BaseBoxType boxTy) {
312 return mlir::dyn_cast<fir::RecordType>(
313 fir::unwrapSequenceType(fir::unwrapRefType(boxTy.getEleTy())));
314}
315
318 auto recTy = unwrapIfDerived(boxTy);
319 return recTy && recTy.getNumLenParams() > 0;
320}
321
323inline bool isDerivedType(fir::BaseBoxType boxTy) {
324 return static_cast<bool>(unwrapIfDerived(boxTy));
325}
326
327#ifndef NDEBUG
328// !fir.ptr<X> and !fir.heap<X> where X is !fir.ptr, !fir.heap, or !fir.ref
329// is undefined and disallowed.
330inline bool singleIndirectionLevel(mlir::Type ty) {
331 return !fir::isa_ref_type(ty);
332}
333#endif
334
337bool isPointerType(mlir::Type ty);
338
340bool isAllocatableType(mlir::Type ty);
341
343bool isBoxNone(mlir::Type ty);
344
347bool isBoxedRecordType(mlir::Type ty);
348
350bool isTypeWithDescriptor(mlir::Type ty);
351
356bool isScalarBoxedRecordType(mlir::Type ty);
357
359mlir::Type getDerivedType(mlir::Type ty);
360
363bool isPolymorphicType(mlir::Type ty);
364
367bool isUnlimitedPolymorphicType(mlir::Type ty);
368
372bool isAssumedType(mlir::Type ty);
373
375bool isAssumedShape(mlir::Type ty);
376
378bool isAllocatableOrPointerArray(mlir::Type ty);
379
383 return static_cast<bool>(unwrapIfDerived(boxTy)) ||
385}
386
388unsigned getBoxRank(mlir::Type boxTy);
389
391mlir::Type unwrapInnerType(mlir::Type ty);
392
394bool isRecordWithAllocatableMember(mlir::Type ty);
395
398bool isRecordWithDescriptorMember(mlir::Type ty);
399
401inline bool isRecordWithTypeParameters(mlir::Type ty) {
402 if (auto recTy = mlir::dyn_cast_or_null<fir::RecordType>(ty))
403 return recTy.isDependentType();
404 return false;
405}
406
408bool isCharacterProcedureTuple(mlir::Type type, bool acceptRawFunc = true);
409
413mlir::Type applyPathToType(mlir::Type rootTy, mlir::ValueRange path);
414
417bool hasAbstractResult(mlir::FunctionType ty);
418
420mlir::Type fromRealTypeID(mlir::MLIRContext *context, llvm::Type::TypeID typeID,
421 fir::KindTy kind);
422
423int getTypeCode(mlir::Type ty, const KindMapping &kindMap);
424
425inline bool BaseBoxType::classof(mlir::Type type) {
426 return mlir::isa<fir::BoxType, fir::ClassType>(type);
427}
428
430inline bool isNoneOrSeqNone(mlir::Type type) {
431 if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(type))
432 return mlir::isa<mlir::NoneType>(seqTy.getEleTy());
433 return mlir::isa<mlir::NoneType>(type);
434}
435
438inline mlir::Type wrapInClassOrBoxType(mlir::Type eleTy,
439 bool isPolymorphic = false,
440 bool isAssumedType = false) {
441 if (isPolymorphic && !isAssumedType)
442 return fir::ClassType::get(eleTy);
443 return fir::BoxType::get(eleTy);
444}
445
452inline mlir::Type updateTypeForUnlimitedPolymorphic(mlir::Type ty) {
453 if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty))
454 return fir::SequenceType::get(
455 seqTy.getShape(), updateTypeForUnlimitedPolymorphic(seqTy.getEleTy()));
456 if (auto heapTy = mlir::dyn_cast<fir::HeapType>(ty))
457 return fir::HeapType::get(
458 updateTypeForUnlimitedPolymorphic(heapTy.getEleTy()));
459 if (auto pointerTy = mlir::dyn_cast<fir::PointerType>(ty))
460 return fir::PointerType::get(
461 updateTypeForUnlimitedPolymorphic(pointerTy.getEleTy()));
462 if (!mlir::isa<mlir::NoneType, fir::RecordType>(ty))
463 return mlir::NoneType::get(ty.getContext());
464 return ty;
465}
466
471mlir::Type changeElementType(mlir::Type type, mlir::Type newElementType,
472 bool turnBoxIntoClass);
473
475inline bool isBoxAddress(mlir::Type t) {
476 return fir::isa_ref_type(t) &&
477 mlir::isa<fir::BaseBoxType>(fir::unwrapRefType(t));
478}
479
481inline bool isBoxAddressOrValue(mlir::Type t) {
482 return mlir::isa<fir::BaseBoxType>(fir::unwrapRefType(t));
483}
484
486inline bool isBoxProcAddressType(mlir::Type t) {
488 return t && mlir::isa<fir::BoxProcType>(t);
489}
490
495std::string getTypeAsString(mlir::Type ty, const KindMapping &kindMap,
496 llvm::StringRef prefix = "");
497
504
506std::pair<std::uint64_t, unsigned short>
507getTypeSizeAndAlignmentOrCrash(mlir::Location loc, mlir::Type ty,
508 const mlir::DataLayout &dl,
509 const fir::KindMapping &kindMap);
510
512std::optional<std::pair<uint64_t, unsigned short>>
513getTypeSizeAndAlignment(mlir::Location loc, mlir::Type ty,
514 const mlir::DataLayout &dl,
515 const fir::KindMapping &kindMap);
516} // namespace fir
517
518#endif // FORTRAN_OPTIMIZER_DIALECT_FIRTYPE_H
This class provides a shared interface for box and class types.
Definition: FIRType.h:40
Attribute
Box attributes.
Definition: FIRType.h:45
BaseBoxType getBoxTypeWithNewAttr(Attribute attr) const
Return the same type, except for the attribute (fir.heap/fir.ptr).
Definition: FIRType.cpp:1328
bool isAssumedRank() const
Is this the box for an assumed rank?
Definition: FIRType.cpp:1348
mlir::Type unwrapInnerType() const
Unwrap element type from fir.heap, fir.ptr and fir.array.
Definition: FIRType.cpp:1280
mlir::Type getEleTy() const
Returns the element type of this box type.
Definition: FIRType.cpp:1274
BaseBoxType getBoxTypeWithNewShape(mlir::Type shapeMold) const
Definition: FIRType.cpp:1309
static bool classof(mlir::Type type)
Methods for support type inquiry through isa, cast, and dyn_cast.
Definition: FIRType.h:425
Definition: KindMapping.h:48
Definition: FIRType.h:77
Definition: AbstractConverter.h:31
bool isa_box_type(mlir::Type t)
Is t a boxed type?
Definition: FIRType.h:112
int getTypeCode(mlir::Type ty, const KindMapping &kindMap)
Return the ISO_C_BINDING intrinsic module value of type ty.
Definition: FIRType.cpp:447
bool isScalarBoxedRecordType(mlir::Type ty)
Definition: FIRType.cpp:306
mlir::Type applyPathToType(mlir::Type rootTy, mlir::ValueRange path)
Definition: FIROps.cpp:4375
std::string getTypeAsString(mlir::Type ty, const KindMapping &kindMap, llvm::StringRef prefix="")
Definition: FIRType.cpp:544
fir::SequenceType unwrapUntilSeqType(mlir::Type t)
Definition: FIRType.h:295
bool sequenceWithNonConstantShape(fir::SequenceType seqTy)
Definition: FIRType.h:230
bool isa_ref_type(mlir::Type t)
Is t a FIR dialect type that implies a memory (de)reference?
Definition: FIRType.h:106
bool isBoxAddressOrValue(mlir::Type t)
Is t a fir.box or class address or value type?
Definition: FIRType.h:481
bool conformsWithPassByRef(mlir::Type t)
Definition: FIRType.h:127
bool isa_builtin_cdevptr_type(mlir::Type t)
Is t type(c_devptr)?
Definition: FIRType.h:150
mlir::Type fromRealTypeID(mlir::MLIRContext *context, llvm::Type::TypeID typeID, fir::KindTy kind)
Convert llvm::Type::TypeID to mlir::Type.
Definition: FIRType.cpp:1248
bool isUnlimitedPolymorphicType(mlir::Type ty)
Definition: FIRType.cpp:366
bool isa_vector(mlir::Type t)
Is t a vector type?
Definition: FIRType.h:178
mlir::Type unwrapPassByRefType(mlir::Type t)
Definition: FIRType.h:273
bool isDerivedType(fir::BaseBoxType boxTy)
Return true iff boxTy wraps a fir::RecordType.
Definition: FIRType.h:323
bool isa_char(mlir::Type t)
Is t a CHARACTER type? Does not check the length.
Definition: FIRType.h:198
bool isBoxedRecordType(mlir::Type ty)
Definition: FIRType.cpp:294
bool isBoxNone(mlir::Type ty)
Return true iff ty is !fir.box<none>.
Definition: FIRType.cpp:288
mlir::Type unwrapSeqOrBoxedSeqType(mlir::Type ty)
Definition: FIRType.cpp:428
bool isBoxAddress(mlir::Type t)
Is t an address to fir.box or class type?
Definition: FIRType.h:475
mlir::Type updateTypeForUnlimitedPolymorphic(mlir::Type ty)
Definition: FIRType.h:452
bool isa_derived(mlir::Type t)
Is t a derived (record) type?
Definition: FIRType.h:132
bool isa_aggregate(mlir::Type t)
Is t a FIR dialect aggregate type?
Definition: FIRType.h:157
bool isDerivedTypeWithLenParams(fir::BaseBoxType boxTy)
Return true iff boxTy wraps a fir::RecordType with length parameters.
Definition: FIRType.h:317
mlir::Type unwrapInnerType(mlir::Type ty)
Return the inner type of the given type.
Definition: FIRType.cpp:378
bool isAssumedShape(mlir::Type ty)
Return true iff ty is the type of an assumed shape array.
Definition: FIRType.cpp:333
bool isCharacterProcedureTuple(mlir::Type type, bool acceptRawFunc=true)
Is this tuple type holding a character function and its result length?
Definition: FIRType.cpp:1230
mlir::Type dyn_cast_ptrEleTy(mlir::Type t)
Definition: FIRType.cpp:216
mlir::Type getDerivedType(mlir::Type ty)
Return the nested RecordType if one if found. Return ty otherwise.
Definition: FIRType.cpp:206
bool isa_fir_or_std_type(mlir::Type t)
Is t any of the FIR dialect or Standard dialect types?
Definition: FIRType.cpp:199
bool isNoneOrSeqNone(mlir::Type type)
Return true iff ty is none or fir.array<none>.
Definition: FIRType.h:430
std::optional< std::pair< uint64_t, unsigned short > > getTypeSizeAndAlignment(mlir::Location loc, mlir::Type ty, const mlir::DataLayout &dl, const fir::KindMapping &kindMap)
This variant returns std::nullopt if an unsupported type is passed.
Definition: FIRType.cpp:1387
fir::RecordType unwrapIfDerived(fir::BaseBoxType boxTy)
Definition: FIRType.h:311
bool boxHasAddendum(fir::BaseBoxType boxTy)
Definition: FIRType.h:382
bool isRecordWithAllocatableMember(mlir::Type ty)
Return true iff ty is a RecordType with members that are allocatable.
Definition: FIRType.cpp:390
unsigned getBoxRank(mlir::Type boxTy)
Get the rank from a !fir.box type.
Definition: FIRType.cpp:439
mlir::Type dyn_cast_ptrOrBoxEleTy(mlir::Type t)
Definition: FIRType.cpp:223
bool isPointerType(mlir::Type ty)
Definition: FIRType.cpp:272
bool isTypeWithDescriptor(mlir::Type ty)
Return true iff ty is a type that contains descriptor information.
Definition: FIRType.cpp:352
bool characterWithDynamicLen(mlir::Type t)
Returns true iff t is a fir.char type and has an unknown length.
Definition: FIRType.h:222
bool isAllocatableType(mlir::Type ty)
Return true iff ty is the type of an ALLOCATABLE entity or value.
Definition: FIRType.cpp:280
mlir::Type changeElementType(mlir::Type type, mlir::Type newElementType, bool turnBoxIntoClass)
Definition: FIRType.cpp:617
bool isPolymorphicType(mlir::Type ty)
Definition: FIRType.cpp:358
bool isa_builtin_cptr_type(mlir::Type t)
Is t type(c_ptr) or type(c_funptr)?
Definition: FIRType.h:135
mlir::Type unwrapAllRefAndSeqType(mlir::Type ty)
Definition: FIRType.cpp:417
bool hasAbstractResult(mlir::FunctionType ty)
Definition: FIRType.cpp:1238
bool isAllocatableOrPointerArray(mlir::Type ty)
Return true iff ty is the type of an allocatable array.
Definition: FIRType.cpp:340
bool isa_integer(mlir::Type t)
Is t an integral type?
Definition: FIRType.h:173
mlir::Type extractSequenceType(mlir::Type ty)
Return the nested sequence type if any.
Definition: FIRType.cpp:260
bool isa_char_string(mlir::Type t)
Is t a CHARACTER type with a LEN other than 1?
Definition: FIRType.h:208
bool isRecordWithDescriptorMember(mlir::Type ty)
Definition: FIRType.cpp:404
bool isBoxProcAddressType(mlir::Type t)
Is this a fir.boxproc address type?
Definition: FIRType.h:486
bool isa_std_type(mlir::Type t)
Is t any of the Standard dialect types?
Definition: FIRType.cpp:195
bool isa_passbyref_type(mlir::Type t)
Definition: FIRType.h:119
std::pair< std::uint64_t, unsigned short > getTypeSizeAndAlignmentOrCrash(mlir::Location loc, mlir::Type ty, const mlir::DataLayout &dl, const fir::KindMapping &kindMap)
This variant terminates the compilation if an unsupported type is passed.
Definition: FIRType.cpp:1439
bool hasDynamicSize(mlir::Type t)
Returns true iff the type t does not have a constant size.
Definition: FIRType.cpp:247
mlir::Type boxMemRefType(fir::BaseBoxType t)
Get the memory reference type of the data pointer from the box type,.
Definition: FIRType.h:248
bool isRecordWithTypeParameters(mlir::Type ty)
Return true iff ty is a RecordType with type parameters.
Definition: FIRType.h:401
bool isAssumedType(mlir::Type ty)
Definition: FIRType.cpp:320
void verifyIntegralType(mlir::Type type)
Definition: FIRType.cpp:653
bool isa_complex(mlir::Type t)
Is t a floating point complex type?
Definition: FIRType.h:191
bool isa_fir_type(mlir::Type t)
Is t any of the FIR dialect types?
Definition: FIRType.cpp:191
mlir::Type wrapInClassOrBoxType(mlir::Type eleTy, bool isPolymorphic=false, bool isAssumedType=false)
Definition: FIRType.h:438
bool isa_trivial(mlir::Type t)
Definition: FIRType.h:202
mlir::Type unwrapSequenceType(mlir::Type t)
If t is a SequenceType return its element type, otherwise return t.
Definition: FIRType.h:256
bool isa_unknown_size_box(mlir::Type t)
Definition: FIRType.cpp:665
bool isa_real(mlir::Type t)
Is t a real type?
Definition: FIRType.h:170
Definition: AbstractConverter.h:27