1//===- FIRTypesTest.cpp ---------------------------------------------------===//
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#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"
13
14struct FIRTypesTest : public testing::Test {
15public:
16 void SetUp() {
17 fir::support::loadDialects(context);
18 kindMap = new fir::KindMapping(&context, kindMapInit, "r42a10c14d28i40l41");
19 }
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";
24};
25
26// Test fir::isPolymorphicType from flang/Optimizer/Dialect/FIRType.h.
27TEST_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");
32 mlir::Type seqRecTy =
33 fir::SequenceType::get({fir::SequenceType::getUnknownExtent()}, recTy);
34
35 // CLASS(T)
36 mlir::Type ty = fir::ClassType::get(recTy);
37 EXPECT_TRUE(fir::isPolymorphicType(ty));
38 EXPECT_TRUE(fir::isPolymorphicType(fir::ReferenceType::get(ty)));
39
40 // CLASS(T), DIMENSION(10)
41 ty = fir::ClassType::get(fir::SequenceType::get({10}, recTy));
42 EXPECT_TRUE(fir::isPolymorphicType(ty));
43
44 // CLASS(T), DIMENSION(:)
45 ty = fir::ClassType::get(seqRecTy);
46 EXPECT_TRUE(fir::isPolymorphicType(ty));
47
48 // CLASS(T), ALLOCATABLE
49 ty = fir::ClassType::get(fir::HeapType::get(recTy));
50 EXPECT_TRUE(fir::isPolymorphicType(ty));
51
52 // CLASS(T), ALLOCATABLE, DIMENSION(:)
53 ty = fir::ClassType::get(fir::HeapType::get(seqRecTy));
54 EXPECT_TRUE(fir::isPolymorphicType(ty));
55
56 // CLASS(T), POINTER
57 ty = fir::ClassType::get(fir::PointerType::get(recTy));
58 EXPECT_TRUE(fir::isPolymorphicType(ty));
59
60 // CLASS(T), POINTER, DIMENSIONS(:)
61 ty = fir::ClassType::get(fir::PointerType::get(seqRecTy));
62 EXPECT_TRUE(fir::isPolymorphicType(ty));
63
64 // CLASS(*)
65 ty = fir::ClassType::get(noneTy);
66 EXPECT_TRUE(fir::isPolymorphicType(ty));
67 EXPECT_TRUE(fir::isPolymorphicType(fir::ReferenceType::get(ty)));
68
69 // TYPE(*)
70 EXPECT_TRUE(fir::isPolymorphicType(fir::BoxType::get(noneTy)));
71
72 // TYPE(*), DIMENSION(:)
73 EXPECT_TRUE(fir::isPolymorphicType(fir::BoxType::get(seqNoneTy)));
74
75 // false tests
76 EXPECT_FALSE(fir::isPolymorphicType(noneTy));
77 EXPECT_FALSE(fir::isPolymorphicType(seqNoneTy));
78}
79
80// Test fir::isUnlimitedPolymorphicType from flang/Optimizer/Dialect/FIRType.h.
81TEST_F(FIRTypesTest, isUnlimitedPolymorphicTypeTest) {
82 mlir::Type noneTy = mlir::NoneType::get(&context);
83 mlir::Type seqNoneTy =
84 fir::SequenceType::get({fir::SequenceType::getUnknownExtent()}, noneTy);
85
86 // CLASS(*)
87 mlir::Type ty = fir::ClassType::get(noneTy);
88 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(ty));
89 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(fir::ReferenceType::get(ty)));
90
91 // CLASS(*), DIMENSION(10)
92 ty = fir::ClassType::get(fir::SequenceType::get({10}, noneTy));
93 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(ty));
94
95 // CLASS(*), DIMENSION(:)
96 ty = fir::ClassType::get(
97 fir::SequenceType::get({fir::SequenceType::getUnknownExtent()}, noneTy));
98 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(ty));
99
100 // CLASS(*), ALLOCATABLE
101 ty = fir::ClassType::get(fir::HeapType::get(noneTy));
102 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(ty));
103
104 // CLASS(*), ALLOCATABLE, DIMENSION(:)
105 ty = fir::ClassType::get(fir::HeapType::get(seqNoneTy));
106 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(ty));
107
108 // CLASS(*), POINTER
109 ty = fir::ClassType::get(fir::PointerType::get(noneTy));
110 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(ty));
111
112 // CLASS(*), POINTER, DIMENSIONS(:)
113 ty = fir::ClassType::get(fir::PointerType::get(seqNoneTy));
114 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(ty));
115
116 // TYPE(*)
117 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(fir::BoxType::get(noneTy)));
118
119 // TYPE(*), DIMENSION(:)
120 EXPECT_TRUE(fir::isUnlimitedPolymorphicType(fir::BoxType::get(seqNoneTy)));
121
122 // false tests
123 EXPECT_FALSE(fir::isUnlimitedPolymorphicType(noneTy));
124 EXPECT_FALSE(fir::isUnlimitedPolymorphicType(seqNoneTy));
125}
126
127// Test fir::isBoxedRecordType from flang/Optimizer/Dialect/FIRType.h.
128TEST_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)));
135
136 // TYPE(T), ALLOCATABLE
137 ty = fir::BoxType::get(fir::HeapType::get(recTy));
138 EXPECT_TRUE(fir::isBoxedRecordType(ty));
139
140 // TYPE(T), POINTER
141 ty = fir::BoxType::get(fir::PointerType::get(recTy));
142 EXPECT_TRUE(fir::isBoxedRecordType(ty));
143
144 // TYPE(T), DIMENSION(10)
145 ty = fir::BoxType::get(fir::SequenceType::get({10}, recTy));
146 EXPECT_TRUE(fir::isBoxedRecordType(ty));
147
148 // TYPE(T), DIMENSION(:)
149 ty = fir::BoxType::get(seqRecTy);
150 EXPECT_TRUE(fir::isBoxedRecordType(ty));
151
152 EXPECT_FALSE(fir::isBoxedRecordType(fir::BoxType::get(
153 fir::ReferenceType::get(mlir::IntegerType::get(&context, 32)))));
154}
155
156// Test fir::isScalarBoxedRecordType from flang/Optimizer/Dialect/FIRType.h.
157TEST_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)));
164
165 // CLASS(T), ALLOCATABLE
166 ty = fir::ClassType::get(fir::HeapType::get(recTy));
167 EXPECT_TRUE(fir::isScalarBoxedRecordType(ty));
168
169 // TYPE(T), ALLOCATABLE
170 ty = fir::BoxType::get(fir::HeapType::get(recTy));
171 EXPECT_TRUE(fir::isScalarBoxedRecordType(ty));
172
173 // TYPE(T), POINTER
174 ty = fir::BoxType::get(fir::PointerType::get(recTy));
175 EXPECT_TRUE(fir::isScalarBoxedRecordType(ty));
176
177 // CLASS(T), POINTER
178 ty = fir::ClassType::get(fir::PointerType::get(recTy));
179 EXPECT_TRUE(fir::isScalarBoxedRecordType(ty));
180
181 // TYPE(T), DIMENSION(10)
182 ty = fir::BoxType::get(fir::SequenceType::get({10}, recTy));
183 EXPECT_FALSE(fir::isScalarBoxedRecordType(ty));
184
185 // TYPE(T), DIMENSION(:)
186 ty = fir::BoxType::get(seqRecTy);
187 EXPECT_FALSE(fir::isScalarBoxedRecordType(ty));
188
189 EXPECT_FALSE(fir::isScalarBoxedRecordType(fir::BoxType::get(
190 fir::ReferenceType::get(mlir::IntegerType::get(&context, 32)))));
191}
192
193TEST_F(FIRTypesTest, updateTypeForUnlimitedPolymorphic) {
194 // RecordType are not changed.
195
196 // !fir.tyep<T> -> !fir.type<T>
197 mlir::Type recTy = fir::RecordType::get(&context, "dt");
198 EXPECT_EQ(recTy, fir::updateTypeForUnlimitedPolymorphic(recTy));
199
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));
203
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));
211
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));
219
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);
228
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};
236
237 for (mlir::Type ty : intrinsicTypes) {
238 // `ty` -> none
239 EXPECT_EQ(none, fir::updateTypeForUnlimitedPolymorphic(ty));
240
241 // !fir.array<10xTY> -> !fir.array<10xnone>
242 mlir::Type arrTy = fir::SequenceType::get({10}, ty);
243 EXPECT_EQ(arrNone, fir::updateTypeForUnlimitedPolymorphic(arrTy));
244
245 // !fir.heap<TY> -> !fir.heap<none>
246 mlir::Type heapTy = fir::HeapType::get(ty);
247 EXPECT_EQ(heapNone, fir::updateTypeForUnlimitedPolymorphic(heapTy));
248
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));
252
253 // !fir.ptr<TY> -> !fir.ptr<none>
254 mlir::Type ptrTy = fir::PointerType::get(ty);
255 EXPECT_EQ(ptrNone, fir::updateTypeForUnlimitedPolymorphic(ptrTy));
256
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));
260 }
261}
262
263TEST_F(FIRTypesTest, getTypeAsString) {
264 EXPECT_EQ("i32",
265 fir::getTypeAsString(mlir::IntegerType::get(&context, 32), *kindMap));
266 EXPECT_EQ("ref_i32",
267 fir::getTypeAsString(
268 fir::ReferenceType::get(mlir::IntegerType::get(&context, 32)),
269 *kindMap));
270 EXPECT_EQ(
271 "f64", fir::getTypeAsString(mlir::FloatType::getF64(&context), *kindMap));
272 EXPECT_EQ(
273 "l8", fir::getTypeAsString(fir::LogicalType::get(&context, 1), *kindMap));
274 EXPECT_EQ("z32",
275 fir::getTypeAsString(
276 mlir::ComplexType::get(mlir::FloatType::getF32(&context)), *kindMap));
277 EXPECT_EQ("c8",
278 fir::getTypeAsString(fir::CharacterType::get(&context, 1, 1), *kindMap));
279 EXPECT_EQ("c8x10",
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));
284 EXPECT_EQ(
285 "idx", fir::getTypeAsString(mlir::IndexType::get(&context), *kindMap));
286 EXPECT_EQ("ptr_i32",
287 fir::getTypeAsString(
288 fir::PointerType::get(mlir::IntegerType::get(&context, 32)),
289 *kindMap));
290 EXPECT_EQ("heap_i32",
291 fir::getTypeAsString(
292 fir::HeapType::get(mlir::IntegerType::get(&context, 32)), *kindMap));
293 EXPECT_EQ("box_i32",
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()},
310 ty);
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)),
315 *kindMap));
316 EXPECT_EQ("boxchar_c8xU",
317 fir::getTypeAsString(fir::BoxCharType::get(&context, 1), *kindMap));
318}
319

source code of flang/unittests/Optimizer/FIRTypesTest.cpp