355 lines · cpp
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-exception6//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), ALLOCATABLE49 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), POINTER57 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 tests76 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(*), ALLOCATABLE101 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(*), POINTER109 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 tests123 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), ALLOCATABLE137 ty = fir::BoxType::get(fir::HeapType::get(recTy));138 EXPECT_TRUE(fir::isBoxedRecordType(ty));139 140 // TYPE(T), POINTER141 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), ALLOCATABLE166 ty = fir::ClassType::get(fir::HeapType::get(recTy));167 EXPECT_TRUE(fir::isScalarBoxedRecordType(ty));168 169 // TYPE(T), ALLOCATABLE170 ty = fir::BoxType::get(fir::HeapType::get(recTy));171 EXPECT_TRUE(fir::isScalarBoxedRecordType(ty));172 173 // TYPE(T), POINTER174 ty = fir::BoxType::get(fir::PointerType::get(recTy));175 EXPECT_TRUE(fir::isScalarBoxedRecordType(ty));176 177 // CLASS(T), POINTER178 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::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` -> none239 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::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 320TEST_F(FIRTypesTest, isVolatileType) {321 mlir::Type i32 = mlir::IntegerType::get(&context, 32);322 323 mlir::Type i32NonVolatileRef = fir::ReferenceType::get(i32);324 mlir::Type i32NonVolatileBox = fir::BoxType::get(i32);325 mlir::Type i32NonVolatileClass = fir::ClassType::get(i32);326 327 // Ensure the default value is false328 EXPECT_EQ(i32NonVolatileRef, fir::ReferenceType::get(i32, false));329 EXPECT_EQ(i32NonVolatileBox, fir::BoxType::get(i32, false));330 EXPECT_EQ(i32NonVolatileClass, fir::ClassType::get(i32, false));331 332 EXPECT_FALSE(fir::isa_volatile_type(i32));333 EXPECT_FALSE(fir::isa_volatile_type(i32NonVolatileRef));334 EXPECT_FALSE(fir::isa_volatile_type(i32NonVolatileBox));335 EXPECT_FALSE(fir::isa_volatile_type(i32NonVolatileClass));336 337 // Should return the same type if it's not capable of representing volatility.338 EXPECT_EQ(i32, fir::updateTypeWithVolatility(i32, true));339 340 mlir::Type i32VolatileRef =341 fir::updateTypeWithVolatility(i32NonVolatileRef, true);342 mlir::Type i32VolatileBox =343 fir::updateTypeWithVolatility(i32NonVolatileBox, true);344 mlir::Type i32VolatileClass =345 fir::updateTypeWithVolatility(i32NonVolatileClass, true);346 347 EXPECT_TRUE(fir::isa_volatile_type(i32VolatileRef));348 EXPECT_TRUE(fir::isa_volatile_type(i32VolatileBox));349 EXPECT_TRUE(fir::isa_volatile_type(i32VolatileClass));350 351 EXPECT_EQ(i32VolatileRef, fir::ReferenceType::get(i32, true));352 EXPECT_EQ(i32VolatileBox, fir::BoxType::get(i32, true));353 EXPECT_EQ(i32VolatileClass, fir::ClassType::get(i32, true));354}355