I am trying to call a C function from Fortran, passing in a string. However, I am seeing different generated calling conventions between gfortran
and flang-new
/ifx
. For example, if my C function has the signature
void check_argument(char name[]);
according to Note 4 of section 18.3.7 of the Standard, I should declare an interface
interface
subroutine c_check_argument_1(name) bind(C, name="check_argument")
use, intrinsic :: iso_c_binding
implicit none
character(c_char), dimension(*) :: name
end subroutine c_check_argument
end interface
where name is an assumed-size array of characters.
However, when I compile with flang-new
, the generated IR has an extra argument inserted (presumably the array size):
declare void @check_argument(ptr, i64) local_unnamed_addr
I can also see this appear in the generated assembly, with an extra variable getting pushed onto the stack before the call.
Another way of declaring the interface is to use c_ptr
(plus c_loc
):
interface
subroutine c_check_argument_2(name) bind(C, name="check_argument")
use, intrinsic :: iso_c_binding
implicit none
type(c_ptr), value :: name
end subroutine c_check_argument
end interface
I would expect that call c_check_argument_1(char_array)
and call c_check_argument_2(c_loc(char_array))
would give the same generated LLVM IR and ASM. However, they do not: Compiler Explorer
On the other hand, gfortran
gives the same ASM for both calls.
Which behavior is correct? It seems odd to me that flang
silently inserts an extra argument.