[flang-commits] [flang] 0cf70a3 - [flang] Allow conversion from boxed derived type to fir.class
Valentin Clement via flang-commits
flang-commits at lists.llvm.org
Sun Oct 9 23:59:18 PDT 2022
Author: Valentin Clement
Date: 2022-10-10T08:59:09+02:00
New Revision: 0cf70a33f296544088cfce5d777acd85b72280a4
URL: https://github.com/llvm/llvm-project/commit/0cf70a33f296544088cfce5d777acd85b72280a4
DIFF: https://github.com/llvm/llvm-project/commit/0cf70a33f296544088cfce5d777acd85b72280a4.diff
LOG: [flang] Allow conversion from boxed derived type to fir.class
This patch updates the fir.convert operation's verifier to allow
conversion from !fir.box<!fir.type<T>> to !fir.class<!fir.type<T>>.
Other conversion involving fir.class are likely needed but will
be added when lowering needs them.
Reviewed By: PeteSteinfeld
Differential Revision: https://reviews.llvm.org/D135445
Added:
Modified:
flang/include/flang/Optimizer/Dialect/FIRType.h
flang/lib/Optimizer/Dialect/FIROps.cpp
flang/lib/Optimizer/Dialect/FIRType.cpp
flang/test/Lower/polymorphic.f90
flang/unittests/Optimizer/FIRTypesTest.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Dialect/FIRType.h b/flang/include/flang/Optimizer/Dialect/FIRType.h
index b2f0c6b018c46..1bd6ed1bf06e9 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRType.h
+++ b/flang/include/flang/Optimizer/Dialect/FIRType.h
@@ -38,6 +38,9 @@ class BaseBoxType : public mlir::Type {
/// Returns the element type of this box type.
mlir::Type getEleTy() const;
+ /// Unwrap element type from fir.heap, fir.ptr and fir.array.
+ mlir::Type unwrapInnerType() const;
+
/// Methods for support type inquiry through isa, cast, and dyn_cast.
static bool classof(mlir::Type type);
};
@@ -273,6 +276,10 @@ bool isPointerType(mlir::Type ty);
/// Return true iff `ty` is the type of an ALLOCATABLE entity or value.
bool isAllocatableType(mlir::Type ty);
+/// Return true iff `ty` is the type of a boxed record type.
+/// e.g. !fir.box<!fir.type<derived>>
+bool isBoxedRecordType(mlir::Type ty);
+
/// Return true iff `ty` is the type of an polymorphic entity or
/// value.
bool isPolymorphicType(mlir::Type ty);
diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp
index 9666677bcd867..7e59506e97afc 100644
--- a/flang/lib/Optimizer/Dialect/FIROps.cpp
+++ b/flang/lib/Optimizer/Dialect/FIROps.cpp
@@ -916,7 +916,8 @@ mlir::LogicalResult fir::ConvertOp::verify() {
(isPointerCompatible(inType) && isIntegerCompatible(outType)) ||
(inType.isa<fir::BoxType>() && outType.isa<fir::BoxType>()) ||
(inType.isa<fir::BoxProcType>() && outType.isa<fir::BoxProcType>()) ||
- (fir::isa_complex(inType) && fir::isa_complex(outType)))
+ (fir::isa_complex(inType) && fir::isa_complex(outType)) ||
+ (fir::isBoxedRecordType(inType) && fir::isPolymorphicType(outType)))
return mlir::success();
return emitOpError("invalid type conversion");
}
diff --git a/flang/lib/Optimizer/Dialect/FIRType.cpp b/flang/lib/Optimizer/Dialect/FIRType.cpp
index 40ebf3760ea3f..67b4d1af7cf17 100644
--- a/flang/lib/Optimizer/Dialect/FIRType.cpp
+++ b/flang/lib/Optimizer/Dialect/FIRType.cpp
@@ -262,6 +262,18 @@ bool isAllocatableType(mlir::Type ty) {
return false;
}
+bool isBoxedRecordType(mlir::Type ty) {
+ if (auto refTy = fir::dyn_cast_ptrEleTy(ty))
+ ty = refTy;
+ if (auto boxTy = ty.dyn_cast<fir::BoxType>()) {
+ if (boxTy.getEleTy().isa<fir::RecordType>())
+ return true;
+ mlir::Type innerType = boxTy.unwrapInnerType();
+ return innerType && innerType.isa<fir::RecordType>();
+ }
+ return false;
+}
+
static bool isAssumedType(mlir::Type ty) {
if (auto boxTy = ty.dyn_cast<fir::BoxType>()) {
if (boxTy.getEleTy().isa<mlir::NoneType>())
@@ -289,17 +301,8 @@ bool isUnlimitedPolymorphicType(mlir::Type ty) {
if (auto clTy = ty.dyn_cast<fir::ClassType>()) {
if (clTy.getEleTy().isa<mlir::NoneType>())
return true;
- mlir::Type innerType =
- llvm::TypeSwitch<mlir::Type, mlir::Type>(clTy.getEleTy())
- .Case<fir::PointerType, fir::HeapType, fir::SequenceType>(
- [](auto ty) {
- mlir::Type eleTy = ty.getEleTy();
- if (auto seqTy = eleTy.dyn_cast<fir::SequenceType>())
- return seqTy.getEleTy();
- return eleTy;
- })
- .Default([](mlir::Type) { return mlir::Type{}; });
- return innerType.isa<mlir::NoneType>();
+ mlir::Type innerType = clTy.unwrapInnerType();
+ return innerType && innerType.isa<mlir::NoneType>();
}
// TYPE(*)
return isAssumedType(ty);
@@ -982,6 +985,17 @@ mlir::Type BaseBoxType::getEleTy() const {
[](auto type) { return type.getEleTy(); });
}
+mlir::Type BaseBoxType::unwrapInnerType() const {
+ return llvm::TypeSwitch<mlir::Type, mlir::Type>(getEleTy())
+ .Case<fir::PointerType, fir::HeapType, fir::SequenceType>([](auto ty) {
+ mlir::Type eleTy = ty.getEleTy();
+ if (auto seqTy = eleTy.dyn_cast<fir::SequenceType>())
+ return seqTy.getEleTy();
+ return eleTy;
+ })
+ .Default([](mlir::Type) { return mlir::Type{}; });
+}
+
//===----------------------------------------------------------------------===//
// FIROpsDialect
//===----------------------------------------------------------------------===//
diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90
index 03e917b82f177..6c690317352a0 100644
--- a/flang/test/Lower/polymorphic.f90
+++ b/flang/test/Lower/polymorphic.f90
@@ -6,6 +6,8 @@ module polymorphic_test
type p1
integer :: a
integer :: b
+ contains
+ procedure :: print
end type
type, extends(p1) :: p2
@@ -27,4 +29,25 @@ subroutine component_access(p)
! CHECK: %[[LOAD:.*]] = fir.load %[[COORD]] : !fir.ref<i32>
! CHECK: %{{.*}} = fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[LOAD]]) : (!fir.ref<i8>, i32) -> i1
+ subroutine print(this)
+ class(p1) :: this
+ end subroutine
+
+ ! Test passing fir.convert accept fir.box<DT> -> fir.class<DT>
+ subroutine check()
+ type(p1) :: t1
+ type(p2) :: t2
+ call t1%print()
+ call t2%print()
+ end subroutine
+
+! CHECK-LABEL: func.func @_QMpolymorphic_testPcheck()
+! CHECK: %[[DT1:.*]] = fir.alloca !fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}> {bindc_name = "t1", uniq_name = "_QMpolymorphic_testFcheckEt1"}
+! CHECK: %[[DT2:.*]] = fir.alloca !fir.type<_QMpolymorphic_testTp2{a:i32,b:i32,c:f32}> {bindc_name = "t2", uniq_name = "_QMpolymorphic_testFcheckEt2"}
+! CHECK: %[[BOX1:.*]] = fir.embox %[[DT1]] : (!fir.ref<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> !fir.box<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>
+! CHECK: %[[CLASS1:.*]] = fir.convert %[[BOX1]] : (!fir.box<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>
+! CHECK: fir.call @_QMpolymorphic_testPprint(%[[CLASS1]]) : (!fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> ()
+! CHECK: %[[BOX2:.*]] = fir.embox %[[DT2]] : (!fir.ref<!fir.type<_QMpolymorphic_testTp2{a:i32,b:i32,c:f32}>>) -> !fir.box<!fir.type<_QMpolymorphic_testTp2{a:i32,b:i32,c:f32}>>
+! CHECK: %[[CLASS2:.*]] = fir.convert %[[BOX2]] : (!fir.box<!fir.type<_QMpolymorphic_testTp2{a:i32,b:i32,c:f32}>>) -> !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>
+! CHECK: fir.call @_QMpolymorphic_testPprint(%[[CLASS2]]) : (!fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>) -> ()
end module
diff --git a/flang/unittests/Optimizer/FIRTypesTest.cpp b/flang/unittests/Optimizer/FIRTypesTest.cpp
index 1a81c2ff426f7..580415e5c8b2d 100644
--- a/flang/unittests/Optimizer/FIRTypesTest.cpp
+++ b/flang/unittests/Optimizer/FIRTypesTest.cpp
@@ -117,3 +117,32 @@ TEST_F(FIRTypesTest, isUnlimitedPolymorphicTypeTest) {
EXPECT_FALSE(fir::isUnlimitedPolymorphicType(noneTy));
EXPECT_FALSE(fir::isUnlimitedPolymorphicType(seqNoneTy));
}
+
+// Test fir::isBoxedRecordType from flang/Optimizer/Dialect/FIRType.h.
+TEST_F(FIRTypesTest, isBoxedRecordType) {
+ mlir::Type recTy = fir::RecordType::get(&context, "dt");
+ mlir::Type seqRecTy =
+ fir::SequenceType::get({fir::SequenceType::getUnknownExtent()}, recTy);
+ mlir::Type ty = fir::BoxType::get(recTy);
+ EXPECT_TRUE(fir::isBoxedRecordType(ty));
+ EXPECT_TRUE(fir::isBoxedRecordType(fir::ReferenceType::get(ty)));
+
+ // TYPE(T), ALLOCATABLE
+ ty = fir::BoxType::get(fir::HeapType::get(recTy));
+ EXPECT_TRUE(fir::isBoxedRecordType(ty));
+
+ // TYPE(T), POINTER
+ ty = fir::BoxType::get(fir::PointerType::get(recTy));
+ EXPECT_TRUE(fir::isBoxedRecordType(ty));
+
+ // TYPE(T), DIMENSION(10)
+ ty = fir::BoxType::get(fir::SequenceType::get({10}, recTy));
+ EXPECT_TRUE(fir::isBoxedRecordType(ty));
+
+ // TYPE(T), DIMENSION(:)
+ ty = fir::BoxType::get(seqRecTy);
+ EXPECT_TRUE(fir::isBoxedRecordType(ty));
+
+ EXPECT_FALSE(fir::isBoxedRecordType(fir::BoxType::get(
+ fir::ReferenceType::get(mlir::IntegerType::get(&context, 32)))));
+}
More information about the flang-commits
mailing list