[J3] [SC22WG5.6562] RE: [ukfortran] bind(C) external linkage issues on MacOS

Malcolm Cohen malcolm at nag-j.co.jp
Mon Mar 18 07:04:03 UTC 2024


Perhaps using something equivalent to the gcc "__attribute__((__common__))"
on the symbol might help? In C one is stuck with the gcc extension, but in
principle the Fortran compiler should be able to do this automatically.

 

Unless this is a slightly different issue, for which the above doesn't work.

 

Cheers,

-- 

..............Malcolm Cohen, NAG Oxford/Tokyo.

 

From: Jeff Hammond <jehammond at nvidia.com> 
Sent: Saturday, March 16, 2024 2:29 AM
To: WG5 <sc22wg5 at open-std.org>
Subject: [ukfortran] [SC22WG5.6552] bind(C) external linkage issues on MacOS

 

This is both an FYI for those of you who use MacOS but also a possible
identification of a problem in how we specify 19.5.1.5 Linkage association.

 

Apple has removed "-commons use_dylibs" in recent versions of MacOS.  This
flag sets a non-default behavior of COMMON symbols (which include linkage
associated bind(C) symbols that are not using obsolescent features) to be
"U" (undefined) instead of "S" (uninitialized, small)
https://linux.die.net/man/1/nm.

 

This flag is required to get a bind(C) module variable that points to a C
global variable to work properly, as is potentially required by MPI.  There
are many reports of failures online with both GCC and Intel compilers (I can
only verify the former).

 

It has been noted that our definition of linkage association may not be
adequate to interact with C shared libraries.  I don't understand this topic
well enough to have an opinion either way.

 

Has anybody else run into this or thought about it enough to know if there
is a way to enhance our definition of linkage association so as to not
require Fortran-specific linker options and behave more like C extern in
shared libraries?

 

Thanks,

Jeff

 

jhammond at Jeff-M2 fortran % gcc -fPIC -shared extern2.c -o libxxx.so &&
gfortran -c extern.F90 && ld extern.o libxxx.so
-L/opt/homebrew/Cellar/gcc/13.2.0/lib/gcc/current/  -lgfortran -commons
use_dylibs -o extern && ./extern ; nm extern | grep MPI

MPIR_F08_MPI_IN_PLACE=0 &MPIR_F08_MPI_IN_PLACE=0x1003a4000
&MPIR_F08_MPI_IN_PLACE=4298784768

LOC(MPI_IN_PLACE)=           4298784768

LOC(buf)=           6168523360

sendbuf=0x1003a4000, sendbuf=4298784768

sendbuf is MPI_IN_PLACE? yes

recvbuf=0x16fac3260, recvbuf=6168523360

*count=1, *datatype=2, *op=3, *comm=4

         911

                 U _MPIR_F08_MPI_IN_PLACE

                 U _MPI_Allreduce

 

 

jhammond at Jeff-M2 fortran % gcc -fPIC -shared extern2.c -o libxxx.so &&
gfortran -c extern.F90 && ld extern.o libxxx.so
-L/opt/homebrew/Cellar/gcc/13.2.0/lib/gcc/current/  -lgfortran  -o extern &&
./extern ; nm extern | grep MPI

MPIR_F08_MPI_IN_PLACE=0 &MPIR_F08_MPI_IN_PLACE=0x102b1c000
&MPIR_F08_MPI_IN_PLACE=4340170752

LOC(MPI_IN_PLACE)=           4339777664

LOC(buf)=           6127137376

sendbuf=0x102abc080, sendbuf=4339777664

sendbuf is MPI_IN_PLACE? no

recvbuf=0x16d34b260, recvbuf=6127137376

*count=1, *datatype=2, *op=3, *comm=4

         911

0000000100008080 S _MPIR_F08_MPI_IN_PLACE

                 U _MPI_Allreduce

 

 

==> extern2.c <==

#include <stdio.h>

#include <stdint.h>

 

int MPIR_F08_MPI_IN_PLACE;

 

void p(void)

{

    printf("MPIR_F08_MPI_IN_PLACE=%d &MPIR_F08_MPI_IN_PLACE=%p
&MPIR_F08_MPI_IN_PLACE=%zu\n",

            MPIR_F08_MPI_IN_PLACE,   &MPIR_F08_MPI_IN_PLACE,
(intptr_t)&MPIR_F08_MPI_IN_PLACE);

}

 

void MPI_Allreduce(void ** sendbuf, void ** recvbuf,

                   int * count, int * datatype,

                   int * op, int * comm, int * ierror)

{

    printf("sendbuf=%p, sendbuf=%zu\n", sendbuf, (intptr_t)sendbuf);

    printf("sendbuf is MPI_IN_PLACE? %s\n",

           (intptr_t)sendbuf==(intptr_t)&MPIR_F08_MPI_IN_PLACE ? "yes" :
"no");

    printf("recvbuf=%p, recvbuf=%zu\n", recvbuf, (intptr_t)recvbuf);

    printf("*count=%d, *datatype=%d, *op=%d, *comm=%d\n",

            *count, *datatype, *op, *comm);

    *ierror = 911;

}

 

==> extern.F90 <==

module mpi

    use iso_c_binding

    !type(c_ptr), bind(C,name="MPI_F_IN_PLACE") :: MPI_IN_PLACE

    integer(c_int), bind(C, name="MPIR_F08_MPI_IN_PLACE"), target ::
MPI_IN_PLACE

    interface

        subroutine p() bind(C,name="p")

        end subroutine

    end interface

    interface

        SUBROUTINE MPI_ALLREDUCE(SENDBUF, RECVBUF, COUNT, DATATYPE, OP,
COMM, IERROR) &

                   bind(C,name="MPI_Allreduce")

            use iso_c_binding

            import :: MPI_IN_PLACE

            !DEC$ ATTRIBUTES NO_ARG_CHECK :: sendbuf,recvbuf

            !GCC$ ATTRIBUTES NO_ARG_CHECK :: sendbuf,recvbuf

            !$PRAGMA IGNORE_TKR sendbuf,recvbuf

            !DIR$ IGNORE_TKR sendbuf,recvbuf

            !IBM* IGNORE_TKR sendbuf,recvbuf

            INTEGER(kind=c_int) :: SENDBUF(*), RECVBUF(*)

            INTEGER(kind=c_int) :: COUNT, DATATYPE, OP, COMM, IERROR

        END SUBROUTINE MPI_ALLREDUCE

    end interface

end module mpi

 

program main

    use mpi

    implicit none

    real :: buf(100)

    integer :: ierror

    call p

    buf = 17

    print*,'LOC(MPI_IN_PLACE)=',LOC(MPI_IN_PLACE)

    print*,'LOC(buf)=',LOC(buf)

    call MPI_ALLREDUCE(MPI_IN_PLACE,buf,1,2,3,4,ierror)

    print*,ierror

end program main

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.j3-fortran.org/pipermail/j3/attachments/20240318/0e09a457/attachment.htm>


More information about the J3 mailing list