1 //===- FIRTypesTest.cpp ---------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "gtest/gtest.h"
10 #include "flang/Optimizer/Dialect/FIRType.h"
11 #include "flang/Optimizer/Dialect/Support/KindMapping.h"
12 #include "flang/Optimizer/Support/InitFIR.h"
14 struct FIRTypesTest
: public testing::Test
{
17 fir::support::loadDialects(context
);
18 kindMap
= new fir::KindMapping(&context
, kindMapInit
, "r42a10c14d28i40l41");
20 mlir::MLIRContext context
;
21 fir::KindMapping
*kindMap
{};
22 std::string kindMapInit
=
23 "i10:80,l3:24,a1:8,r54:Double,r62:X86_FP80,r11:PPC_FP128";
26 // Test fir::isPolymorphicType from flang/Optimizer/Dialect/FIRType.h.
27 TEST_F(FIRTypesTest
, isPolymorphicTypeTest
) {
28 mlir::Type noneTy
= mlir::NoneType::get(&context
);
29 mlir::Type seqNoneTy
=
30 fir::SequenceType::get({fir::SequenceType::getUnknownExtent()}, noneTy
);
31 mlir::Type recTy
= fir::RecordType::get(&context
, "dt");
33 fir::SequenceType::get({fir::SequenceType::getUnknownExtent()}, recTy
);
36 mlir::Type ty
= fir::ClassType::get(recTy
);
37 EXPECT_TRUE(fir::isPolymorphicType(ty
));
38 EXPECT_TRUE(fir::isPolymorphicType(fir::ReferenceType::get(ty
)));
40 // CLASS(T), DIMENSION(10)
41 ty
= fir::ClassType::get(fir::SequenceType::get({10}, recTy
));
42 EXPECT_TRUE(fir::isPolymorphicType(ty
));
44 // CLASS(T), DIMENSION(:)
45 ty
= fir::ClassType::get(seqRecTy
);
46 EXPECT_TRUE(fir::isPolymorphicType(ty
));
48 // CLASS(T), ALLOCATABLE
49 ty
= fir::ClassType::get(fir::HeapType::get(recTy
));
50 EXPECT_TRUE(fir::isPolymorphicType(ty
));
52 // CLASS(T), ALLOCATABLE, DIMENSION(:)
53 ty
= fir::ClassType::get(fir::HeapType::get(seqRecTy
));
54 EXPECT_TRUE(fir::isPolymorphicType(ty
));
57 ty
= fir::ClassType::get(fir::PointerType::get(recTy
));
58 EXPECT_TRUE(fir::isPolymorphicType(ty
));
60 // CLASS(T), POINTER, DIMENSIONS(:)
61 ty
= fir::ClassType::get(fir::PointerType::get(seqRecTy
));
62 EXPECT_TRUE(fir::isPolymorphicType(ty
));
65 ty
= fir::ClassType::get(noneTy
);
66 EXPECT_TRUE(fir::isPolymorphicType(ty
));
67 EXPECT_TRUE(fir::isPolymorphicType(fir::ReferenceType::get(ty
)));
70 EXPECT_TRUE(fir::isPolymorphicType(fir::BoxType::get(noneTy
)));
72 // TYPE(*), DIMENSION(:)
73 EXPECT_TRUE(fir::isPolymorphicType(fir::BoxType::get(seqNoneTy
)));
76 EXPECT_FALSE(fir::isPolymorphicType(noneTy
));
77 EXPECT_FALSE(fir::isPolymorphicType(seqNoneTy
));
80 // Test fir::isUnlimitedPolymorphicType from flang/Optimizer/Dialect/FIRType.h.
81 TEST_F(FIRTypesTest
, isUnlimitedPolymorphicTypeTest
) {
82 mlir::Type noneTy
= mlir::NoneType::get(&context
);
83 mlir::Type seqNoneTy
=
84 fir::SequenceType::get({fir::SequenceType::getUnknownExtent()}, noneTy
);
87 mlir::Type ty
= fir::ClassType::get(noneTy
);
88 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(ty
));
89 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(fir::ReferenceType::get(ty
)));
91 // CLASS(*), DIMENSION(10)
92 ty
= fir::ClassType::get(fir::SequenceType::get({10}, noneTy
));
93 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(ty
));
95 // CLASS(*), DIMENSION(:)
96 ty
= fir::ClassType::get(
97 fir::SequenceType::get({fir::SequenceType::getUnknownExtent()}, noneTy
));
98 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(ty
));
100 // CLASS(*), ALLOCATABLE
101 ty
= fir::ClassType::get(fir::HeapType::get(noneTy
));
102 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(ty
));
104 // CLASS(*), ALLOCATABLE, DIMENSION(:)
105 ty
= fir::ClassType::get(fir::HeapType::get(seqNoneTy
));
106 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(ty
));
109 ty
= fir::ClassType::get(fir::PointerType::get(noneTy
));
110 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(ty
));
112 // CLASS(*), POINTER, DIMENSIONS(:)
113 ty
= fir::ClassType::get(fir::PointerType::get(seqNoneTy
));
114 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(ty
));
117 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(fir::BoxType::get(noneTy
)));
119 // TYPE(*), DIMENSION(:)
120 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(fir::BoxType::get(seqNoneTy
)));
123 EXPECT_FALSE(fir::isUnlimitedPolymorphicType(noneTy
));
124 EXPECT_FALSE(fir::isUnlimitedPolymorphicType(seqNoneTy
));
127 // Test fir::isBoxedRecordType from flang/Optimizer/Dialect/FIRType.h.
128 TEST_F(FIRTypesTest
, isBoxedRecordType
) {
129 mlir::Type recTy
= fir::RecordType::get(&context
, "dt");
130 mlir::Type seqRecTy
=
131 fir::SequenceType::get({fir::SequenceType::getUnknownExtent()}, recTy
);
132 mlir::Type ty
= fir::BoxType::get(recTy
);
133 EXPECT_TRUE(fir::isBoxedRecordType(ty
));
134 EXPECT_TRUE(fir::isBoxedRecordType(fir::ReferenceType::get(ty
)));
136 // TYPE(T), ALLOCATABLE
137 ty
= fir::BoxType::get(fir::HeapType::get(recTy
));
138 EXPECT_TRUE(fir::isBoxedRecordType(ty
));
141 ty
= fir::BoxType::get(fir::PointerType::get(recTy
));
142 EXPECT_TRUE(fir::isBoxedRecordType(ty
));
144 // TYPE(T), DIMENSION(10)
145 ty
= fir::BoxType::get(fir::SequenceType::get({10}, recTy
));
146 EXPECT_TRUE(fir::isBoxedRecordType(ty
));
148 // TYPE(T), DIMENSION(:)
149 ty
= fir::BoxType::get(seqRecTy
);
150 EXPECT_TRUE(fir::isBoxedRecordType(ty
));
152 EXPECT_FALSE(fir::isBoxedRecordType(fir::BoxType::get(
153 fir::ReferenceType::get(mlir::IntegerType::get(&context
, 32)))));
156 // Test fir::isScalarBoxedRecordType from flang/Optimizer/Dialect/FIRType.h.
157 TEST_F(FIRTypesTest
, isScalarBoxedRecordType
) {
158 mlir::Type recTy
= fir::RecordType::get(&context
, "dt");
159 mlir::Type seqRecTy
=
160 fir::SequenceType::get({fir::SequenceType::getUnknownExtent()}, recTy
);
161 mlir::Type ty
= fir::BoxType::get(recTy
);
162 EXPECT_TRUE(fir::isScalarBoxedRecordType(ty
));
163 EXPECT_TRUE(fir::isScalarBoxedRecordType(fir::ReferenceType::get(ty
)));
165 // CLASS(T), ALLOCATABLE
166 ty
= fir::ClassType::get(fir::HeapType::get(recTy
));
167 EXPECT_TRUE(fir::isScalarBoxedRecordType(ty
));
169 // TYPE(T), ALLOCATABLE
170 ty
= fir::BoxType::get(fir::HeapType::get(recTy
));
171 EXPECT_TRUE(fir::isScalarBoxedRecordType(ty
));
174 ty
= fir::BoxType::get(fir::PointerType::get(recTy
));
175 EXPECT_TRUE(fir::isScalarBoxedRecordType(ty
));
178 ty
= fir::ClassType::get(fir::PointerType::get(recTy
));
179 EXPECT_TRUE(fir::isScalarBoxedRecordType(ty
));
181 // TYPE(T), DIMENSION(10)
182 ty
= fir::BoxType::get(fir::SequenceType::get({10}, recTy
));
183 EXPECT_FALSE(fir::isScalarBoxedRecordType(ty
));
185 // TYPE(T), DIMENSION(:)
186 ty
= fir::BoxType::get(seqRecTy
);
187 EXPECT_FALSE(fir::isScalarBoxedRecordType(ty
));
189 EXPECT_FALSE(fir::isScalarBoxedRecordType(fir::BoxType::get(
190 fir::ReferenceType::get(mlir::IntegerType::get(&context
, 32)))));
193 TEST_F(FIRTypesTest
, updateTypeForUnlimitedPolymorphic
) {
194 // RecordType are not changed.
196 // !fir.tyep<T> -> !fir.type<T>
197 mlir::Type recTy
= fir::RecordType::get(&context
, "dt");
198 EXPECT_EQ(recTy
, fir::updateTypeForUnlimitedPolymorphic(recTy
));
200 // !fir.array<2x!fir.type<T>> -> !fir.array<2x!fir.type<T>>
201 mlir::Type arrRecTy
= fir::SequenceType::get({2}, recTy
);
202 EXPECT_EQ(arrRecTy
, fir::updateTypeForUnlimitedPolymorphic(arrRecTy
));
204 // !fir.heap<!fir.type<T>> -> !fir.heap<!fir.type<T>>
205 mlir::Type heapTy
= fir::HeapType::get(recTy
);
206 EXPECT_EQ(heapTy
, fir::updateTypeForUnlimitedPolymorphic(heapTy
));
207 // !fir.heap<!fir.array<2x!fir.type<T>>> ->
208 // !fir.heap<!fir.array<2x!fir.type<T>>>
209 mlir::Type heapArrTy
= fir::HeapType::get(arrRecTy
);
210 EXPECT_EQ(heapArrTy
, fir::updateTypeForUnlimitedPolymorphic(heapArrTy
));
212 // !fir.ptr<!fir.type<T>> -> !fir.ptr<!fir.type<T>>
213 mlir::Type ptrTy
= fir::PointerType::get(recTy
);
214 EXPECT_EQ(ptrTy
, fir::updateTypeForUnlimitedPolymorphic(ptrTy
));
215 // !fir.ptr<!fir.array<2x!fir.type<T>>> ->
216 // !fir.ptr<!fir.array<2x!fir.type<T>>>
217 mlir::Type ptrArrTy
= fir::PointerType::get(arrRecTy
);
218 EXPECT_EQ(ptrArrTy
, fir::updateTypeForUnlimitedPolymorphic(ptrArrTy
));
220 // When updating intrinsic types the array, pointer and heap types are kept.
221 // only the inner element type is changed to `none`.
222 mlir::Type none
= mlir::NoneType::get(&context
);
223 mlir::Type arrNone
= fir::SequenceType::get({10}, none
);
224 mlir::Type heapNone
= fir::HeapType::get(none
);
225 mlir::Type heapArrNone
= fir::HeapType::get(arrNone
);
226 mlir::Type ptrNone
= fir::PointerType::get(none
);
227 mlir::Type ptrArrNone
= fir::PointerType::get(arrNone
);
229 mlir::Type i32Ty
= mlir::IntegerType::get(&context
, 32);
230 mlir::Type f32Ty
= mlir::FloatType::getF32(&context
);
231 mlir::Type l1Ty
= fir::LogicalType::get(&context
, 1);
232 mlir::Type cplx4Ty
= fir::ComplexType::get(&context
, 4);
233 mlir::Type char1Ty
= fir::CharacterType::get(&context
, 1, 10);
234 llvm::SmallVector
<mlir::Type
> intrinsicTypes
= {
235 i32Ty
, f32Ty
, l1Ty
, cplx4Ty
, char1Ty
};
237 for (mlir::Type ty
: intrinsicTypes
) {
239 EXPECT_EQ(none
, fir::updateTypeForUnlimitedPolymorphic(ty
));
241 // !fir.array<10xTY> -> !fir.array<10xnone>
242 mlir::Type arrTy
= fir::SequenceType::get({10}, ty
);
243 EXPECT_EQ(arrNone
, fir::updateTypeForUnlimitedPolymorphic(arrTy
));
245 // !fir.heap<TY> -> !fir.heap<none>
246 mlir::Type heapTy
= fir::HeapType::get(ty
);
247 EXPECT_EQ(heapNone
, fir::updateTypeForUnlimitedPolymorphic(heapTy
));
249 // !fir.heap<!fir.array<10xTY>> -> !fir.heap<!fir.array<10xnone>>
250 mlir::Type heapArrTy
= fir::HeapType::get(arrTy
);
251 EXPECT_EQ(heapArrNone
, fir::updateTypeForUnlimitedPolymorphic(heapArrTy
));
253 // !fir.ptr<TY> -> !fir.ptr<none>
254 mlir::Type ptrTy
= fir::PointerType::get(ty
);
255 EXPECT_EQ(ptrNone
, fir::updateTypeForUnlimitedPolymorphic(ptrTy
));
257 // !fir.ptr<!fir.array<10xTY>> -> !fir.ptr<!fir.array<10xnone>>
258 mlir::Type ptrArrTy
= fir::PointerType::get(arrTy
);
259 EXPECT_EQ(ptrArrNone
, fir::updateTypeForUnlimitedPolymorphic(ptrArrTy
));
263 TEST_F(FIRTypesTest
, getTypeAsString
) {
265 fir::getTypeAsString(mlir::IntegerType::get(&context
, 32), *kindMap
));
267 fir::getTypeAsString(
268 fir::ReferenceType::get(mlir::IntegerType::get(&context
, 32)),
271 "f64", fir::getTypeAsString(mlir::FloatType::getF64(&context
), *kindMap
));
273 "l8", fir::getTypeAsString(fir::LogicalType::get(&context
, 1), *kindMap
));
275 fir::getTypeAsString(
276 mlir::ComplexType::get(mlir::FloatType::getF32(&context
)), *kindMap
));
278 fir::getTypeAsString(fir::CharacterType::get(&context
, 1, 1), *kindMap
));
280 fir::getTypeAsString(fir::CharacterType::get(&context
, 1, 10), *kindMap
));
281 mlir::Type ty
= mlir::IntegerType::get(&context
, 64);
282 mlir::Type arrTy
= fir::SequenceType::get({10, 20}, ty
);
283 EXPECT_EQ("10x20xi64", fir::getTypeAsString(arrTy
, *kindMap
));
285 "idx", fir::getTypeAsString(mlir::IndexType::get(&context
), *kindMap
));
287 fir::getTypeAsString(
288 fir::PointerType::get(mlir::IntegerType::get(&context
, 32)),
290 EXPECT_EQ("heap_i32",
291 fir::getTypeAsString(
292 fir::HeapType::get(mlir::IntegerType::get(&context
, 32)), *kindMap
));
294 fir::getTypeAsString(
295 fir::BoxType::get(mlir::IntegerType::get(&context
, 32)), *kindMap
));
296 EXPECT_EQ("class_i32",
297 fir::getTypeAsString(
298 fir::ClassType::get(mlir::IntegerType::get(&context
, 32)), *kindMap
));
299 EXPECT_EQ("class_none",
300 fir::getTypeAsString(
301 fir::ClassType::get(mlir::NoneType::get(&context
)), *kindMap
));
302 auto derivedTy
= fir::RecordType::get(&context
, "derived");
303 llvm::SmallVector
<std::pair
<std::string
, mlir::Type
>> components
;
304 components
.emplace_back("p1", mlir::IntegerType::get(&context
, 64));
305 derivedTy
.finalize({}, components
);
306 EXPECT_EQ("rec_derived", fir::getTypeAsString(derivedTy
, *kindMap
));
307 mlir::Type dynArrTy
=
308 fir::SequenceType::get({fir::SequenceType::getUnknownExtent(),
309 fir::SequenceType::getUnknownExtent()},
311 EXPECT_EQ("UxUxi64", fir::getTypeAsString(dynArrTy
, *kindMap
));
312 EXPECT_EQ("llvmptr_i32",
313 fir::getTypeAsString(
314 fir::LLVMPointerType::get(mlir::IntegerType::get(&context
, 32)),