Index: flang/lib/Lower/Bridge.cpp =================================================================== --- flang/lib/Lower/Bridge.cpp +++ flang/lib/Lower/Bridge.cpp @@ -2729,6 +2729,14 @@ addSymbol(sym, res); } + void mapTrivialByValue(const Fortran::semantics::Symbol &sym, + mlir::Value val) { + mlir::Location loc = toLocation(); + mlir::Value res = builder->create(loc, val.getType()); + builder->create(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. @@ -2758,6 +2766,10 @@ 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 { Index: flang/lib/Lower/CallInterface.cpp =================================================================== --- flang/lib/Lower/CallInterface.cpp +++ flang/lib/Lower/CallInterface.cpp @@ -929,6 +929,9 @@ if (isBindC) { passBy = PassEntityBy::Value; prop = Property::Value; + if (type.isa()) + fir::emitFatalError( + loc, "array with VALUE attribute is not interoperable"); if (fir::isa_builtin_cptr_type(type)) { auto recTy = type.dyn_cast(); mlir::Type fieldTy = recTy.getTypeList()[0].second; Index: flang/test/Lower/call-by-value.f90 =================================================================== --- flang/test/Lower/call-by-value.f90 +++ 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 @@ 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 +! CHECK: fir.call @_QPinternal_call(%[[VAL_1]]) : (!fir.ref) -> () +! 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 +! CHECK: fir.call @_QPinternal_call2(%[[VAL_1]]) : (!fir.ref) -> () +! 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> +! CHECK: fir.call @_QPinternal_call3(%[[VAL_1]]) : (!fir.ref>) -> () +! 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>, index) +! CHECK: %[[VAL_2:.*]] = arith.constant 1 : index +! CHECK: %[[VAL_3:.*]] = fir.emboxchar %[[VAL_1]]#0, %[[VAL_2]] : (!fir.ref>, 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 Index: flang/test/Lower/call.f90 =================================================================== --- flang/test/Lower/call.f90 +++ flang/test/Lower/call.f90 @@ -47,11 +47,14 @@ ! 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 ! 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 +! 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> ! CHECK: %[[LOAD_CHARBOX:.*]] = fir.load %[[CHARBOX]] : !fir.ref> ! CHECK: fir.store %[[LOAD_CHARBOX]] to %[[RESULT]] : !fir.ref>