diff --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp --- a/flang/lib/Lower/ConvertExpr.cpp +++ b/flang/lib/Lower/ConvertExpr.cpp @@ -4654,6 +4654,37 @@ } break; case PassBy::Box: case PassBy::MutableBox: + // Handle polymorphic passed object. + if (fir::isPolymorphicType(argTy)) { + if (isArray(*expr)) { + ExtValue exv = asScalarRef(*expr); + mlir::Value tdesc; + if (fir::isPolymorphicType(fir::getBase(exv).getType())) { + mlir::Type tdescType = + fir::TypeDescType::get(mlir::NoneType::get(builder.getContext())); + tdesc = builder.create( + loc, tdescType, fir::getBase(exv)); + } + mlir::Type baseTy = + fir::dyn_cast_ptrOrBoxEleTy(fir::getBase(exv).getType()); + mlir::Type innerTy = llvm::TypeSwitch(baseTy) + .Case([](auto ty) { return ty.getEleTy(); }) + .Default([](mlir::Type t) {return t; }); + + operands.emplace_back([=](IterSpace iters) -> ExtValue { + mlir::Value coord = builder.create( + loc, fir::ReferenceType::get(innerTy), fir::getBase(exv), iters.iterVec()); + mlir::Value empty; + mlir::ValueRange emptyRange; + return builder.create(loc, fir::ClassType::get(innerTy), + coord, empty, empty, emptyRange, tdesc); + }); + } else { + PushSemantics(ConstituentSemantics::BoxValue); + operands.emplace_back(genElementalArgument(*expr)); + } + break; + } // See C15100 and C15101 fir::emitFatalError(loc, "cannot be POINTER, ALLOCATABLE"); } diff --git a/flang/test/Lower/polymorphic.f90 b/flang/test/Lower/polymorphic.f90 --- a/flang/test/Lower/polymorphic.f90 +++ b/flang/test/Lower/polymorphic.f90 @@ -9,6 +9,7 @@ contains procedure :: print procedure :: assign_p1_int + procedure :: elemental_fct generic :: assignment(=) => assign_p1_int procedure :: host_assoc end type @@ -48,6 +49,11 @@ ! CHECK: fir.store %[[THIS]] to %[[COORD_OF_CLASS]] : !fir.ref>> ! CHECK: fir.call @_QMpolymorphic_testFhost_assocPinternal(%[[TUPLE]]) {{.*}} : (!fir.ref>>>) -> () + elemental integer function elemental_fct(this) + class(p1), intent(In) :: this + elemental_fct = this%a + end function + ! Test correct access to polymorphic entity component. subroutine component_access(p) class(p1) :: p @@ -446,4 +452,95 @@ ! CHECK: %[[B:.*]] = fir.load %[[COORD_B]] : !fir.ref ! CHECK: %{{.*}} = fir.call @_FortranAioOutputInteger32(%{{.*}}, %[[B]]) {{.*}} : (!fir.ref, i32) -> i1 + subroutine test_elemental_array() + type(p1) :: p(5) + print *, p%elemental_fct() + end subroutine + +! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_elemental_array() { +! CHECK: %[[P:.*]] = fir.alloca !fir.array<5x!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {bindc_name = "p", uniq_name = "_QMpolymorphic_testFtest_elemental_arrayEp"} +! CHECK: %[[C5:.*]] = arith.constant 5 : index +! CHECK: %[[TMP:.*]] = fir.allocmem !fir.array<5xi32> +! CHECK: %[[SHAPE:.*]] = fir.shape %[[C5]] : (index) -> !fir.shape<1> +! CHECK: %[[ARRAY_LOAD_TMP:.*]] = fir.array_load %[[TMP]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.array<5xi32> +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.subi %[[C5]], %[[C1]] : index +! CHECK: %[[LOOP_RES:.*]] = fir.do_loop %[[IND:.*]] = %[[C0]] to %[[UB]] step %[[C1]] unordered iter_args(%[[ARG1:.*]] = %[[ARRAY_LOAD_TMP]]) -> (!fir.array<5xi32>) { +! CHECK: %[[COORD:.*]] = fir.coordinate_of %[[P]], %[[IND]] : (!fir.ref>>, index) -> !fir.ref> +! CHECK: %[[EMBOXED:.*]] = fir.embox %[[COORD]] : (!fir.ref>) -> !fir.class> +! CHECK: %[[RES:.*]] = fir.call @_QMpolymorphic_testPelemental_fct(%[[EMBOXED]]) {{.*}} : (!fir.class>) -> i32 +! CHECK: %[[ARR_UP:.*]] = fir.array_update %[[ARG1]], %[[RES]], %[[IND]] : (!fir.array<5xi32>, i32, index) -> !fir.array<5xi32> +! CHECK: fir.result %[[ARR_UP]] : !fir.array<5xi32> +! CHECK: } +! CHECK: fir.array_merge_store %[[ARRAY_LOAD_TMP]], %[[LOOP_RES]] to %[[TMP]] : !fir.array<5xi32>, !fir.array<5xi32>, !fir.heap> +! CHECK: %[[SHAPE:.*]] = fir.shape %[[C5]] : (index) -> !fir.shape<1> +! CHECK: %[[EMBOXED_TMP:.*]] = fir.embox %[[TMP]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box> +! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[EMBOXED_TMP]] : (!fir.box>) -> !fir.box +! CHECK: %{{.*}} = fir.call @_FortranAioOutputDescriptor(%{{.*}}, %[[BOX_NONE]]) {{.*}} : (!fir.ref, !fir.box) -> i1 +! CHECK: fir.freemem %[[TMP]] : !fir.heap> + + subroutine test_elemental_poly_array(p) + class(p1) :: p(5) + print *, p%elemental_fct() + end subroutine + +! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_elemental_poly_array( +! CHECK-SAME: %[[P:.*]]: !fir.class>> {fir.bindc_name = "p"}) { +! CHECK: %[[C5:.*]] = arith.constant 5 : index +! CHECK: %[[TDESC:.*]] = fir.box_tdesc %[[P]] : (!fir.class>>) -> !fir.tdesc +! CHECK: %[[TMP:.*]] = fir.allocmem !fir.array<5xi32> +! CHECK: %[[SHAPE:.*]] = fir.shape %[[C5]] : (index) -> !fir.shape<1> +! CHECK: %[[ARRAY_LOAD_TMP:.*]] = fir.array_load %[[TMP]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.array<5xi32> +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[UB:.*]] = arith.subi %[[C5]], %[[C1]] : index +! CHECK: %[[LOOP_RES:.*]] = fir.do_loop %[[IND:.*]] = %[[C0]] to %[[UB]] step %[[C1]] unordered iter_args(%[[ARG:.*]] = %[[ARRAY_LOAD_TMP]]) -> (!fir.array<5xi32>) { +! CHECK: %[[COORD:.*]] = fir.coordinate_of %[[P]], %[[IND]] : (!fir.class>>, index) -> !fir.ref> +! CHECK: %[[EMBOXED:.*]] = fir.embox %[[COORD]] tdesc %[[TDESC]] : (!fir.ref>, !fir.tdesc) -> !fir.class> +! CHECK: %[[RES:.*]] = fir.dispatch "elemental_fct"(%[[EMBOXED]] : !fir.class>) (%15 : !fir.class>) -> i32 {pass_arg_pos = 0 : i32} +! CHECK: %[[ARR_UP:.*]] = fir.array_update %[[ARG]], %[[RES]], %[[IND]] : (!fir.array<5xi32>, i32, index) -> !fir.array<5xi32> +! CHECK: fir.result %[[ARR_UP]] : !fir.array<5xi32> +! CHECK: } +! CHECK: fir.array_merge_store %[[ARRAY_LOAD_TMP]], %[[LOOP_RES]] to %[[TMP]] : !fir.array<5xi32>, !fir.array<5xi32>, !fir.heap> +! CHECK: %[[SHAPE:.*]] = fir.shape %[[C5]] : (index) -> !fir.shape<1> +! CHECK: %[[EMBOXED_TMP:.*]] = fir.embox %[[TMP]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<1>) -> !fir.box> +! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[EMBOXED_TMP]] : (!fir.box>) -> !fir.box +! CHECK: %{{.*}} = fir.call @_FortranAioOutputDescriptor(%{{.*}}, %[[BOX_NONE]]) {{.*}} : (!fir.ref, !fir.box) -> i1 +! CHECK: fir.freemem %[[TMP]] : !fir.heap> + + subroutine test_elemental_poly_array_2d(p) + class(p1) :: p(5,5) + print *, p%elemental_fct() + end subroutine + +! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_elemental_poly_array_2d( +! CHECK-SAME: %[[P]]: !fir.class>> {fir.bindc_name = "p"}) { +! CHECK: %[[C5:.*]] = arith.constant 5 : index +! CHECK: %[[C5_0:.*]] = arith.constant 5 : index +! CHECK: %[[TDESC:.*]] = fir.box_tdesc %[[P]] : (!fir.class>>) -> !fir.tdesc +! CHECK: %[[TMP:.*]] = fir.allocmem !fir.array<5x5xi32> +! CHECK: %[[SHAPE:.*]] = fir.shape %[[C5]], %[[C5_0]] : (index, index) -> !fir.shape<2> +! CHECK: %[[ARRAY_LOAD_TMP:.*]] = fir.array_load %[[TMP]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<2>) -> !fir.array<5x5xi32> +! CHECK: %[[C1:.*]] = arith.constant 1 : index +! CHECK: %[[C0:.*]] = arith.constant 0 : index +! CHECK: %[[UB0:.*]] = arith.subi %[[C5]], %[[C1]] : index +! CHECK: %[[UB1:.*]] = arith.subi %[[C5_0]], %[[C1]] : index +! CHECK: %[[LOOP_RES:.*]] = fir.do_loop %[[IND0:.*]] = %[[C0]] to %[[UB1]] step %[[C1]] unordered iter_args(%[[ARG:.*]] = %[[ARRAY_LOAD_TMP]]) -> (!fir.array<5x5xi32>) { +! CHECK: %[[LOOP_RES0:.*]] = fir.do_loop %[[IND1:.*]] = %[[C0]] to %[[UB0]] step %[[C1]] unordered iter_args(%[[ARG0:.*]] = %[[ARG]]) -> (!fir.array<5x5xi32>) { +! CHECK: %[[COORD:.*]] = fir.coordinate_of %[[P]], %[[IND1]], %[[IND0]] : (!fir.class>>, index, index) -> !fir.ref> +! CHECK: %[[EMBOXED:.*]] = fir.embox %[[COORD]] tdesc %[[TDESC]] : (!fir.ref>, !fir.tdesc) -> !fir.class> +! CHECK: %[[RES:.*]] = fir.dispatch "elemental_fct"(%[[EMBOXED]] : !fir.class>) (%17 : !fir.class>) -> i32 {pass_arg_pos = 0 : i32} +! CHECK: %[[ARR_UP:.*]] = fir.array_update %[[ARG0]], %[[RES]], %[[IND1]], %[[IND0]] : (!fir.array<5x5xi32>, i32, index, index) -> !fir.array<5x5xi32> +! CHECK: fir.result %[[ARR_UP]] : !fir.array<5x5xi32> +! CHECK: } +! CHECK: fir.result %[[LOOP_RES0]] : !fir.array<5x5xi32> +! CHECK: } +! CHECK: fir.array_merge_store %[[ARRAY_LOAD_TMP]], %[[LOOP_RES]] to %[[TMP]] : !fir.array<5x5xi32>, !fir.array<5x5xi32>, !fir.heap> +! CHECK: %[[SHAPE:.*]] = fir.shape %[[C5]], %[[C5_0]] : (index, index) -> !fir.shape<2> +! CHECK: %[[EMBOXED_TMP:.*]] = fir.embox %[[TMP]](%[[SHAPE]]) : (!fir.heap>, !fir.shape<2>) -> !fir.box> +! CHECK: %[[BOX_NONE:.*]] = fir.convert %[[EMBOXED_TMP]] : (!fir.box>) -> !fir.box +! CHECK: %{{.*}} = fir.call @_FortranAioOutputDescriptor(%{{.*}}, %[[BOX_NONE]]) fastmath : (!fir.ref, !fir.box) -> i1 +! CHECK: fir.freemem %[[TMP]] : !fir.heap> + end module