xref: /llvm-project/flang/unittests/Optimizer/FIRTypesTest.cpp (revision f023da12d12635f5fba436e825cbfc999e28e623)
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 
14 struct FIRTypesTest : public testing::Test {
15 public:
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.
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");
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.
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);
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.
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)));
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.
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)));
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 
193 TEST_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::Float32Type::get(&context);
231   mlir::Type l1Ty = fir::LogicalType::get(&context, 1);
232   mlir::Type cplx32Ty = mlir::ComplexType::get(f32Ty);
233   mlir::Type char1Ty = fir::CharacterType::get(&context, 1, 10);
234   llvm::SmallVector<mlir::Type> intrinsicTypes = {
235       i32Ty, f32Ty, l1Ty, cplx32Ty, 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 
263 TEST_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::Float64Type::get(&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::Float32Type::get(&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