forked from OSchip/llvm-project
[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
This commit is contained in:
parent
a835b92e6c
commit
0cf70a33f2
|
@ -38,6 +38,9 @@ public:
|
|||
/// 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);
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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 @@ module polymorphic_test
|
|||
! 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
|
||||
|
|
|
@ -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)))));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue