Skip to content

Commit d7f5c64

Browse files
committed
[Flang] Handle %VAL arguments correctly
Internal procedures expect reference parameters. However, when %VAL is used, the argument should be passed by value. Create a temporary variable in call generation and pass the address to avoid a type conversion error. Fixes #118239
1 parent 35b2276 commit d7f5c64

File tree

2 files changed

+42
-5
lines changed

2 files changed

+42
-5
lines changed

flang/lib/Lower/ConvertCall.cpp

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -494,10 +494,20 @@ Fortran::lower::genCallOpAndResult(
494494
// arguments of any type and vice versa.
495495
mlir::Value cast;
496496
auto *context = builder.getContext();
497-
if (mlir::isa<fir::BoxProcType>(snd) &&
498-
mlir::isa<mlir::FunctionType>(fst.getType())) {
499-
auto funcTy = mlir::FunctionType::get(context, {}, {});
500-
auto boxProcTy = builder.getBoxProcType(funcTy);
497+
498+
// Special handling for %VAL arguments: internal procedures expect
499+
// reference parameters. When %VAL is used, the argument should be
500+
// passed by value. So we need to create a temporary variable and
501+
// pass its address to avoid a type conversion error.
502+
if (fir::isa_ref_type(snd) && !fir::isa_ref_type(fst.getType()) &&
503+
fir::dyn_cast_ptrEleTy(snd) == fst.getType()) {
504+
mlir::Value temp = builder.createTemporary(loc, fst.getType());
505+
builder.create<fir::StoreOp>(loc, fst, temp);
506+
cast = temp;
507+
} else if (mlir::isa<fir::BoxProcType>(snd) &&
508+
mlir::isa<mlir::FunctionType>(fst.getType())) {
509+
mlir::FunctionType funcTy = mlir::FunctionType::get(context, {}, {});
510+
fir::BoxProcType boxProcTy = builder.getBoxProcType(funcTy);
501511
if (mlir::Value host = argumentHostAssocs(converter, fst)) {
502512
cast = fir::EmboxProcOp::create(builder, loc, boxProcTy,
503513
llvm::ArrayRef<mlir::Value>{fst, host});
@@ -1637,7 +1647,20 @@ void prepareUserCallArguments(
16371647
(*cleanup)();
16381648
break;
16391649
}
1640-
caller.placeInput(arg, builder.createConvert(loc, argTy, value));
1650+
// For %VAL arguments, we should pass the value directly without
1651+
// conversion to reference types. If argTy is different from value type,
1652+
// it might be due to signature mismatch with internal procedures.
1653+
if (argTy == value.getType())
1654+
caller.placeInput(arg, value);
1655+
else if (fir::isa_ref_type(argTy) &&
1656+
fir::dyn_cast_ptrEleTy(argTy) == value.getType()) {
1657+
// We're trying to convert value to reference - create temporary
1658+
mlir::Value temp = builder.createTemporary(loc, value.getType());
1659+
builder.create<fir::StoreOp>(loc, value, temp);
1660+
caller.placeInput(arg, temp);
1661+
} else
1662+
caller.placeInput(arg, builder.createConvert(loc, argTy, value));
1663+
16411664
} break;
16421665
case PassBy::BaseAddressValueAttribute:
16431666
case PassBy::CharBoxValueAttribute:
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
! RUN: bbc %s -emit-fir -o - | FileCheck %s
2+
3+
program main
4+
logical::a1
5+
data a1/.true./
6+
call sa(%val(a1))
7+
! CHECK: fir.load %3 : !fir.ref<!fir.logical<4>>
8+
! CHECK: fir.convert %13 : (!fir.logical<4>) -> i1
9+
write(6,*) "a1 = ", a1
10+
end program main
11+
12+
subroutine sa(x1)
13+
logical::x1
14+
end subroutine sa

0 commit comments

Comments
 (0)