Skip to content

Commit 262dad4

Browse files
committed
[flang] Deal with NULL() passed as actual arg to unlimited polymorphic dummy
NULL() passed as actual argument to a procedure with an optional dummy argument is represented with `fir.box<none>` type. When the dummy argument is polymoprhic or unlimited polymorphic, the SelectOp will complain if the types of the two arguments are not identical. Add a conversion from `fir.box<none>` to `fir.class<none>` in that case. Other situations with optional will require a fir.rebox and will be done in a follow up patch. Reviewed By: PeteSteinfeld Differential Revision: https://reviews.llvm.org/D142203
1 parent 4dbf3f2 commit 262dad4

File tree

4 files changed

+42
-0
lines changed

4 files changed

+42
-0
lines changed

flang/include/flang/Optimizer/Dialect/FIRType.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,9 @@ bool isPointerType(mlir::Type ty);
276276
/// Return true iff `ty` is the type of an ALLOCATABLE entity or value.
277277
bool isAllocatableType(mlir::Type ty);
278278

279+
/// Return true iff `ty` is !fir.box<none>.
280+
bool isBoxNone(mlir::Type ty);
281+
279282
/// Return true iff `ty` is the type of a boxed record type.
280283
/// e.g. !fir.box<!fir.type<derived>>
281284
bool isBoxedRecordType(mlir::Type ty);

flang/lib/Lower/ConvertExpr.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2704,6 +2704,17 @@ class ScalarExprLowering {
27042704
/// has the dummy attributes in BIND(C) contexts.
27052705
mlir::Value box = builder.createBox(
27062706
loc, fir::factory::genMutableBoxRead(builder, loc, mutableBox));
2707+
2708+
// NULL() passed as argument is passed as a !fir.box<none>. Since
2709+
// select op requires the same type for its two argument, convert
2710+
// !fir.box<none> to !fir.class<none> when the argument is
2711+
// polymorphic.
2712+
if (fir::isBoxNone(box.getType()) && fir::isPolymorphicType(argTy))
2713+
box = builder.createConvert(
2714+
loc,
2715+
fir::ClassType::get(mlir::NoneType::get(builder.getContext())),
2716+
box);
2717+
27072718
// Need the box types to be exactly similar for the selectOp.
27082719
mlir::Value convertedBox = builder.createConvert(loc, argTy, box);
27092720
caller.placeInput(arg, builder.create<mlir::arith::SelectOp>(

flang/lib/Optimizer/Dialect/FIRType.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,12 @@ bool isAllocatableType(mlir::Type ty) {
272272
return false;
273273
}
274274

275+
bool isBoxNone(mlir::Type ty) {
276+
if (auto box = ty.dyn_cast<fir::BoxType>())
277+
return box.getEleTy().isa<mlir::NoneType>();
278+
return false;
279+
}
280+
275281
bool isBoxedRecordType(mlir::Type ty) {
276282
if (auto refTy = fir::dyn_cast_ptrEleTy(ty))
277283
ty = refTy;

flang/test/Lower/polymorphic.f90

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,28 @@ subroutine rebox_up_to_record_type(p)
767767
! CHECK: %[[REBOX:.*]] = fir.rebox %[[LOAD_P]](%{{.*}}) : (!fir.class<!fir.heap<!fir.array<?x?xnone>>>, !fir.shift<2>) -> !fir.box<!fir.ptr<!fir.array<?x?x!fir.type<_QMpolymorphic_testTnon_extensible{d:i32}>>>>
768768
! CHECK: fir.store %[[REBOX]] to %[[T]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?x!fir.type<_QMpolymorphic_testTnon_extensible{d:i32}>>>>>
769769

770+
subroutine sub_with_poly_optional(a)
771+
class(*), optional :: a
772+
end subroutine
773+
774+
subroutine test_call_with_null()
775+
call sub_with_poly_optional(null())
776+
end subroutine
777+
778+
! CHECK-LABEL: func.func @_QMpolymorphic_testPtest_call_with_null() {
779+
! CHECK: %[[NULL_LLVM_PTR:.*]] = fir.alloca !fir.llvm_ptr<none>
780+
! CHECK: %[[NULL_BOX_NONE:.*]] = fir.convert %[[NULL_LLVM_PTR]] : (!fir.ref<!fir.llvm_ptr<none>>) -> !fir.ref<!fir.box<none>>
781+
! CHECK: %[[BOX_NONE:.*]] = fir.load %[[NULL_BOX_NONE]] : !fir.ref<!fir.box<none>>
782+
! CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX_NONE]] : (!fir.box<none>) -> !fir.ref<none>
783+
! CHECK: %[[BOX_ADDR_I64:.*]] = fir.convert %[[BOX_ADDR]] : (!fir.ref<none>) -> i64
784+
! CHECK: %[[C0:.*]] = arith.constant 0 : i64
785+
! CHECK: %[[IS_ALLOCATED_OR_ASSOCIATED:.*]] = arith.cmpi ne, %[[BOX_ADDR_I64]], %[[C0]] : i64
786+
! CHECK: %[[ABSENT:.*]] = fir.absent !fir.class<none>
787+
! CHECK: %[[BOX_NONE:.*]] = fir.load %[[NULL_BOX_NONE]] : !fir.ref<!fir.box<none>>
788+
! CHECK: %[[CLASS_NONE:.*]] = fir.convert %[[BOX_NONE]] : (!fir.box<none>) -> !fir.class<none>
789+
! CHECK: %[[ARG:.*]] = arith.select %[[IS_ALLOCATED_OR_ASSOCIATED]], %[[CLASS_NONE]], %[[ABSENT]] : !fir.class<none>
790+
! CHECK: fir.call @_QMpolymorphic_testPsub_with_poly_optional(%[[ARG]]) {{.*}} : (!fir.class<none>) -> ()
791+
770792
end module
771793

772794
program test

0 commit comments

Comments
 (0)