[flang-commits] [flang] 205b474 - [flang] Fix the trivial type passed as value with bind(C)
Peixin Qiao via flang-commits
flang-commits at lists.llvm.org
Mon Oct 17 08:27:49 PDT 2022
Author: Peixin Qiao
Date: 2022-10-17T23:27:17+08:00
New Revision: 205b47401ed6517cc34e473838e1d307715cc9a4
URL: https://github.com/llvm/llvm-project/commit/205b47401ed6517cc34e473838e1d307715cc9a4
DIFF: https://github.com/llvm/llvm-project/commit/205b47401ed6517cc34e473838e1d307715cc9a4.diff
LOG: [flang] Fix the trivial type passed as value with bind(C)
In the callee side, the value cannot be used directly. For example, the
dummy argument is lhs variable or the dummy argument is passed to
another procedure as actual argument.
Fix this by allocating one temporary storage and store the value. Then
map the symbol of dummy argument to the `mlir::Value` of the temporary.
Reviewed By: jeanPerier
Differential Revision: https://reviews.llvm.org/D136009
Added:
Modified:
flang/lib/Lower/Bridge.cpp
flang/lib/Lower/CallInterface.cpp
flang/test/Lower/call-by-value.f90
flang/test/Lower/call.f90
Removed:
################################################################################
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index ac29207e31a4..1ef6538d700b 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -2738,6 +2738,14 @@ class FirConverter : public Fortran::lower::AbstractConverter {
addSymbol(sym, res);
}
+ void mapTrivialByValue(const Fortran::semantics::Symbol &sym,
+ mlir::Value val) {
+ mlir::Location loc = toLocation();
+ mlir::Value res = builder->create<fir::AllocaOp>(loc, val.getType());
+ builder->create<fir::StoreOp>(loc, val, res);
+ addSymbol(sym, res);
+ }
+
/// Map mlir function block arguments to the corresponding Fortran dummy
/// variables. When the result is passed as a hidden argument, the Fortran
/// result is also mapped. The symbol map is used to hold this mapping.
@@ -2767,6 +2775,10 @@ class FirConverter : public Fortran::lower::AbstractConverter {
mapCPtrArgByValue(arg.entity->get(), arg.firArgument);
return;
}
+ if (fir::isa_trivial(argTy)) {
+ mapTrivialByValue(arg.entity->get(), arg.firArgument);
+ return;
+ }
}
addSymbol(arg.entity->get(), arg.firArgument);
} else {
diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index 6758797b781b..71d772282172 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -929,6 +929,9 @@ class Fortran::lower::CallInterfaceImpl {
if (isBindC) {
passBy = PassEntityBy::Value;
prop = Property::Value;
+ if (type.isa<fir::SequenceType>())
+ fir::emitFatalError(
+ loc, "array with VALUE attribute is not interoperable");
if (fir::isa_builtin_cptr_type(type)) {
auto recTy = type.dyn_cast<fir::RecordType>();
mlir::Type fieldTy = recTy.getTypeList()[0].second;
diff --git a/flang/test/Lower/call-by-value.f90 b/flang/test/Lower/call-by-value.f90
index 02f399a36ef2..717da1afd99e 100644
--- a/flang/test/Lower/call-by-value.f90
+++ b/flang/test/Lower/call-by-value.f90
@@ -1,5 +1,14 @@
! Test for PassBy::Value
! RUN: bbc -emit-fir %s -o - | FileCheck %s
+
+!CHECK-LABEL: func @_QQmain()
+!CHECK: %[[LOGICAL:.*]] = fir.alloca !fir.logical<4>
+!CHECK: %false = arith.constant false
+!CHECK: %[[VALUE:.*]] = fir.convert %false : (i1) -> !fir.logical<4>
+!CHECK: fir.store %[[VALUE]] to %[[LOGICAL]]
+!CHECK: %[[LOAD:.*]] = fir.load %[[LOGICAL]]
+!CHECK: fir.call @omp_set_nested(%[[LOAD]]) : {{.*}}
+
program call_by_value
interface
subroutine omp_set_nested(enable) bind(c)
@@ -11,10 +20,56 @@ end subroutine omp_set_nested
do_nested = .FALSE.
call omp_set_nested(do_nested)
end program call_by_value
-!CHECK-LABEL: func @_QQmain()
-!CHECK: %[[LOGICAL:.*]] = fir.alloca !fir.logical<4>
-!CHECK: %false = arith.constant false
-!CHECK: %[[VALUE:.*]] = fir.convert %false : (i1) -> !fir.logical<4>
-!CHECK: fir.store %[[VALUE]] to %[[LOGICAL]]
-!CHECK: %[[LOAD:.*]] = fir.load %[[LOGICAL]]
-!CHECK: fir.call @omp_set_nested(%[[LOAD]]) : {{.*}}
+
+! CHECK-LABEL: func.func @test_integer_value(
+! CHECK-SAME: %[[VAL_0:.*]]: i32 {fir.bindc_name = "x"}) attributes {fir.bindc_name = "test_integer_value"} {
+! CHECK: %[[VAL_1:.*]] = fir.alloca i32
+! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref<i32>
+! CHECK: fir.call @_QPinternal_call(%[[VAL_1]]) : (!fir.ref<i32>) -> ()
+! CHECK: return
+! CHECK: }
+
+subroutine test_integer_value(x) bind(c)
+ integer, value :: x
+ call internal_call(x)
+end
+
+! CHECK-LABEL: func.func @test_real_value(
+! CHECK-SAME: %[[VAL_0:.*]]: f32 {fir.bindc_name = "x"}) attributes {fir.bindc_name = "test_real_value"} {
+! CHECK: %[[VAL_1:.*]] = fir.alloca f32
+! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref<f32>
+! CHECK: fir.call @_QPinternal_call2(%[[VAL_1]]) : (!fir.ref<f32>) -> ()
+! CHECK: return
+! CHECK: }
+
+subroutine test_real_value(x) bind(c)
+ real, value :: x
+ call internal_call2(x)
+end
+
+! CHECK-LABEL: func.func @test_complex_value(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.complex<4> {fir.bindc_name = "x"}) attributes {fir.bindc_name = "test_complex_value"} {
+! CHECK: %[[VAL_1:.*]] = fir.alloca !fir.complex<4>
+! CHECK: fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref<!fir.complex<4>>
+! CHECK: fir.call @_QPinternal_call3(%[[VAL_1]]) : (!fir.ref<!fir.complex<4>>) -> ()
+! CHECK: return
+! CHECK: }
+
+subroutine test_complex_value(x) bind(c)
+ complex, value :: x
+ call internal_call3(x)
+end
+
+! CHECK-LABEL: func.func @test_char_value(
+! CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> {fir.bindc_name = "x"}) attributes {fir.bindc_name = "test_char_value"} {
+! CHECK: %[[VAL_1:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
+! CHECK: %[[VAL_2:.*]] = arith.constant 1 : index
+! CHECK: %[[VAL_3:.*]] = fir.emboxchar %[[VAL_1]]#0, %[[VAL_2]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
+! CHECK: fir.call @_QPinternal_call4(%[[VAL_3]]) : (!fir.boxchar<1>) -> ()
+! CHECK: return
+! CHECK: }
+
+subroutine test_char_value(x) bind(c)
+ character(1), value :: x
+ call internal_call4(x)
+end
diff --git a/flang/test/Lower/call.f90 b/flang/test/Lower/call.f90
index de636eec4321..ef8d418f2dde 100644
--- a/flang/test/Lower/call.f90
+++ b/flang/test/Lower/call.f90
@@ -47,11 +47,14 @@ function f_int_to_char(i) bind(c, name="f_int_to_char")
! CHECK-LABEL: func.func @f_int_to_char(
! CHECK-SAME: %[[ARG0:.*]]: i32 {fir.bindc_name = "i"}) -> !fir.char<1> attributes {fir.bindc_name = "f_int_to_char"} {
! CHECK: %[[CHARBOX:.*]] = fir.alloca !fir.char<1> {adapt.valuebyref}
+! CHECK: %[[INT_I:.*]] = fir.alloca i32
+! CHECK: fir.store %[[ARG0]] to %[[INT_I]] : !fir.ref<i32>
! CHECK: %[[RESULT:.*]] = fir.alloca !fir.char<1> {bindc_name = "f_int_to_char", uniq_name = "_QFf_int_to_charEf_int_to_char"}
-! CHECK: %[[ARG0_I64:.*]] = fir.convert %[[ARG0]] : (i32) -> i64
+! CHECK: %[[ARG0_2:.*]] = fir.load %[[INT_I]] : !fir.ref<i32>
+! CHECK: %[[ARG0_I64:.*]] = fir.convert %[[ARG0_2]] : (i32) -> i64
! CHECK: %[[ARG0_I8:.*]] = fir.convert %[[ARG0_I64]] : (i64) -> i8
! CHECK: %[[UNDEF:.*]] = fir.undefined !fir.char<1>
-! CHECK: %[[CHAR_RES:.*]] = fir.insert_value %4, %3, [0 : index] : (!fir.char<1>, i8) -> !fir.char<1>
+! CHECK: %[[CHAR_RES:.*]] = fir.insert_value %[[UNDEF]], %[[ARG0_I8]], [0 : index] : (!fir.char<1>, i8) -> !fir.char<1>
! CHECK: fir.store %[[CHAR_RES]] to %[[CHARBOX]] : !fir.ref<!fir.char<1>>
! CHECK: %[[LOAD_CHARBOX:.*]] = fir.load %[[CHARBOX]] : !fir.ref<!fir.char<1>>
! CHECK: fir.store %[[LOAD_CHARBOX]] to %[[RESULT]] : !fir.ref<!fir.char<1>>
More information about the flang-commits
mailing list