[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