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