Skip to content

Commit 225f181

Browse files
authored
[Flang] Handle %VAL arguments correctly (#157186)
Internal procedures expect reference parameters. However, when %VAL is used, the argument should be passed by value. Forward the loaded address and skip conversion to avoid a type conversion error. Fixes #118239
1 parent 6b4803f commit 225f181

File tree

3 files changed

+59
-5
lines changed

3 files changed

+59
-5
lines changed

flang/lib/Lower/ConvertCall.cpp

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -515,10 +515,19 @@ Fortran::lower::genCallOpAndResult(
515515
// arguments of any type and vice versa.
516516
mlir::Value cast;
517517
auto *context = builder.getContext();
518-
if (mlir::isa<fir::BoxProcType>(snd) &&
519-
mlir::isa<mlir::FunctionType>(fst.getType())) {
520-
auto funcTy = mlir::FunctionType::get(context, {}, {});
521-
auto boxProcTy = builder.getBoxProcType(funcTy);
518+
519+
// Special handling for %VAL arguments: internal procedures expect
520+
// reference parameters. When %VAL is used, the argument should be
521+
// passed by value. Pass the originally loaded value.
522+
if (fir::isa_ref_type(snd) && !fir::isa_ref_type(fst.getType()) &&
523+
fir::dyn_cast_ptrEleTy(snd) == fst.getType()) {
524+
auto loadOp = mlir::cast<fir::LoadOp>(fst.getDefiningOp());
525+
mlir::Value originalStorage = loadOp.getMemref();
526+
cast = originalStorage;
527+
} else if (mlir::isa<fir::BoxProcType>(snd) &&
528+
mlir::isa<mlir::FunctionType>(fst.getType())) {
529+
mlir::FunctionType funcTy = mlir::FunctionType::get(context, {}, {});
530+
fir::BoxProcType boxProcTy = builder.getBoxProcType(funcTy);
522531
if (mlir::Value host = argumentHostAssocs(converter, fst)) {
523532
cast = fir::EmboxProcOp::create(builder, loc, boxProcTy,
524533
llvm::ArrayRef<mlir::Value>{fst, host});
@@ -1658,7 +1667,19 @@ void prepareUserCallArguments(
16581667
(*cleanup)();
16591668
break;
16601669
}
1661-
caller.placeInput(arg, builder.createConvert(loc, argTy, value));
1670+
// For %VAL arguments, we should pass the value directly without
1671+
// conversion to reference types. If argTy is different from value type,
1672+
// it might be due to signature mismatch with internal procedures.
1673+
if (argTy == value.getType())
1674+
caller.placeInput(arg, value);
1675+
else if (fir::isa_ref_type(argTy) &&
1676+
fir::dyn_cast_ptrEleTy(argTy) == value.getType()) {
1677+
auto loadOp = mlir::cast<fir::LoadOp>(value.getDefiningOp());
1678+
mlir::Value originalStorage = loadOp.getMemref();
1679+
caller.placeInput(arg, originalStorage);
1680+
} else
1681+
caller.placeInput(arg, builder.createConvert(loc, argTy, value));
1682+
16621683
} break;
16631684
case PassBy::BaseAddressValueAttribute:
16641685
case PassBy::CharBoxValueAttribute:
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
! RUN: flang -fc1 -emit-hlfir %s -o - | FileCheck %s
2+
3+
program main
4+
logical::a1
5+
data a1/.true./
6+
call sa(%val(a1))
7+
! CHECK: %[[A1_ADDR:.*]] = fir.address_of(@_QFEa1) : !fir.ref<!fir.logical<4>>
8+
! CHECK: %[[A1_DECL:.*]]:2 = hlfir.declare %[[A1_ADDR]] {uniq_name = "_QFEa1"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
9+
! CHECK: fir.call @_QPsa(%[[A1_DECL]]#0) fastmath<contract> : (!fir.ref<!fir.logical<4>>) -> ()
10+
! CHECK: func.func @_QPsa(%[[SA_ARG:.*]]: !fir.ref<!fir.logical<4>> {fir.bindc_name = "x1"}) {
11+
write(6,*) "a1 = ", a1
12+
end program main
13+
14+
subroutine sa(x1)
15+
logical::x1
16+
end subroutine sa
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
! RUN: flang -fc1 -emit-hlfir %s -o - | FileCheck %s
2+
3+
program main
4+
logical::a1
5+
data a1/.true./
6+
call sb(%val(a1))
7+
! CHECK: %[[A1_ADDR:.*]] = fir.address_of(@_QFEa1) : !fir.ref<!fir.logical<4>>
8+
! CHECK: %[[A1_DECL:.*]]:2 = hlfir.declare %[[A1_ADDR]] {uniq_name = "_QFEa1"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
9+
! CHECK: %[[A1_LOADED:.*]] = fir.load %[[A1_DECL]]#0 : !fir.ref<!fir.logical<4>>
10+
! CHECK: fir.call @_QFPsb(%[[A1_LOADED]]) fastmath<contract> : (!fir.logical<4>) -> ()
11+
! CHECK: func.func private @_QFPsb(%[[SB_ARG:.*]]: !fir.logical<4> {fir.bindc_name = "x1"})
12+
write(6,*) "a1 = ", a1
13+
contains
14+
subroutine sb(x1)
15+
logical, value :: x1
16+
end subroutine sb
17+
end program main

0 commit comments

Comments
 (0)