From 33c29a82a9b3b8a0354a5b5bd75b462505602107 Mon Sep 17 00:00:00 2001 From: Valentin Clement Date: Tue, 21 Feb 2023 10:14:00 +0100 Subject: [PATCH] [flang] Use runtime Assign when rhs is polymorphic Use the runtime when there lhs or rhs is polymorphic. The runtime allows to deal better with polymorphic entities and aliasing. Reviewed By: PeteSteinfeld Differential Revision: https://reviews.llvm.org/D144418 --- flang/lib/Lower/Bridge.cpp | 21 ++++++++++++++------- flang/test/Lower/polymorphic.f90 | 18 ++++++++++++++++++ 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp index 0a2cf3c..65993f5 100644 --- a/flang/lib/Lower/Bridge.cpp +++ b/flang/lib/Lower/Bridge.cpp @@ -2854,13 +2854,20 @@ private: std::optional lhsType = assign.lhs.GetType(); assert(lhsType && "lhs cannot be typeless"); - - // Assignment to polymorphic allocatables may require changing the - // variable dynamic type (See Fortran 2018 10.2.1.3 p3). - if ((lhsType->IsPolymorphic() || - lhsType->IsUnlimitedPolymorphic()) && - Fortran::lower::isWholeAllocatable(assign.lhs)) { - mlir::Value lhs = genExprMutableBox(loc, assign.lhs).getAddr(); + std::optional rhsType = + assign.rhs.GetType(); + + // Assignment to/from polymorphic entities are done with the + // runtime. + if (lhsType->IsPolymorphic() || + lhsType->IsUnlimitedPolymorphic() || + rhsType->IsPolymorphic() || + rhsType->IsUnlimitedPolymorphic()) { + mlir::Value lhs; + if (Fortran::lower::isWholeAllocatable(assign.lhs)) + lhs = genExprMutableBox(loc, assign.lhs).getAddr(); + else + lhs = fir::getBase(genExprBox(loc, assign.lhs, stmtCtx)); mlir::Value rhs = fir::getBase(genExprBox(loc, assign.rhs, stmtCtx)); fir::runtime::genAssign(*builder, loc, lhs, rhs); diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90 index 6935261..50efe02 100644 --- a/flang/test/Lower/polymorphic.f90 +++ b/flang/test/Lower/polymorphic.f90 @@ -933,6 +933,24 @@ module polymorphic_test class(*), optional, intent(in) :: up end subroutine + function rhs() + class(p1), pointer :: rhs + end function + + subroutine test_rhs_assign(a) + type(p1) :: a + a = rhs() + end subroutine + +! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_rhs_assign( +! CHECK-SAME: %[[ARG0:.*]]: !fir.ref> {fir.bindc_name = "a"}) { +! CHECK: %[[RES:.*]] = fir.alloca !fir.class>> {bindc_name = ".result"} +! CHECK: %[[A:.*]] = fir.embox %[[ARG0]] : (!fir.ref>) -> !fir.box> +! CHECK: %[[LOAD_RES:.*]] = fir.load %[[RES]] : !fir.ref>>> +! CHECK: %[[A_NONE:.*]] = fir.convert %[[A]] : (!fir.box>) -> !fir.ref> +! CHECK: %[[RES_NONE:.*]] = fir.convert %[[LOAD_RES]] : (!fir.class>>) -> !fir.box +! CHECK: %{{.*}} = fir.call @_FortranAAssign(%[[A_NONE]], %[[RES_NONE]], %{{.*}}, %{{.*}}) {{.*}} : (!fir.ref>, !fir.box, !fir.ref, i32) -> none + end module program test -- 2.7.4