From 160b576290260b41ea0107aef3524424ea46f315 Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Wed, 27 Mar 2024 22:50:17 -0500 Subject: [PATCH 1/8] abi: split fortran related APIs to mpi_abi_fort.h The Fortran related APIs are meant for interoperation from C to Fortran, and it only can be implemented by a Fortran binding implementation. Split the header allows an independent Fortran binding implementation. For most C MPI code, it won't need mpi_abi_fort.h nor a Fortran binding. For those C code that need Fortran inter-op APIs, they must be linked to a Fortran binding library, e.g. libmpifort.so and likely also linked to Fortran runtime. --- src/binding/abi/mpi_abi.h | 98 ++----------------- src/binding/abi_fortran/mpi_abi_fort.h | 129 +++++++++++++++++++++++++ 2 files changed, 139 insertions(+), 88 deletions(-) create mode 100644 src/binding/abi_fortran/mpi_abi_fort.h diff --git a/src/binding/abi/mpi_abi.h b/src/binding/abi/mpi_abi.h index a4047c35203..e87793b51d9 100644 --- a/src/binding/abi/mpi_abi.h +++ b/src/binding/abi/mpi_abi.h @@ -37,14 +37,6 @@ typedef MPI_ABI_Offset MPI_Offset; typedef MPI_ABI_Count MPI_Count; #undef MPI_ABI_Count -/* MPI_Fint must match the Fortran default INTEGER kind. */ -/* It is often equivalent to C int but most compilers support wider options. */ -#if !defined(MPI_ABI_Fint) -#define MPI_ABI_Fint int -#endif -typedef MPI_ABI_Fint MPI_Fint; -#undef MPI_ABI_Fint - typedef struct { int MPI_SOURCE; int MPI_TAG; @@ -126,12 +118,14 @@ typedef struct MPI_ABI_Datatype* MPI_Datatype; #define MPI_DOUBLE ((MPI_Datatype)0x00000214) #define MPI_C_DOUBLE_COMPLEX ((MPI_Datatype)0x00000216) #define MPI_CXX_DOUBLE_COMPLEX ((MPI_Datatype)0x00000217) +/* #define MPI_LOGICAL ((MPI_Datatype)0x00000218) #define MPI_INTEGER ((MPI_Datatype)0x00000219) #define MPI_REAL ((MPI_Datatype)0x0000021a) #define MPI_COMPLEX ((MPI_Datatype)0x0000021b) #define MPI_DOUBLE_PRECISION ((MPI_Datatype)0x0000021c) #define MPI_DOUBLE_COMPLEX ((MPI_Datatype)0x0000021d) +*/ #define MPI_LONG_DOUBLE ((MPI_Datatype)0x00000220) #define MPI_C_LONG_DOUBLE_COMPLEX ((MPI_Datatype)0x00000224) #define MPI_CXX_LONG_DOUBLE_COMPLEX ((MPI_Datatype)0x00000225) @@ -141,9 +135,11 @@ typedef struct MPI_ABI_Datatype* MPI_Datatype; #define MPI_2INT ((MPI_Datatype)0x0000022b) #define MPI_SHORT_INT ((MPI_Datatype)0x0000022c) #define MPI_LONG_DOUBLE_INT ((MPI_Datatype)0x0000022d) +/* #define MPI_2REAL ((MPI_Datatype)0x00000230) #define MPI_2DOUBLE_PRECISION ((MPI_Datatype)0x00000231) #define MPI_2INTEGER ((MPI_Datatype)0x00000232) +*/ #define MPI_C_BOOL ((MPI_Datatype)0x00000238) #define MPI_CXX_BOOL ((MPI_Datatype)0x00000239) #define MPI_WCHAR ((MPI_Datatype)0x0000023c) @@ -159,6 +155,7 @@ typedef struct MPI_ABI_Datatype* MPI_Datatype; #define MPI_UINT32_T ((MPI_Datatype)0x00000251) #define MPI_INT64_T ((MPI_Datatype)0x00000258) #define MPI_UINT64_T ((MPI_Datatype)0x00000259) +/* #define MPIX_LOGICAL1 ((MPI_Datatype)0x000002c0) #define MPI_INTEGER1 ((MPI_Datatype)0x000002c1) #define MPI_CHARACTER ((MPI_Datatype)0x000002c3) @@ -178,22 +175,7 @@ typedef struct MPI_ABI_Datatype* MPI_Datatype; #define MPI_REAL16 ((MPI_Datatype)0x000002e2) #define MPI_COMPLEX16 ((MPI_Datatype)0x000002e3) #define MPI_COMPLEX32 ((MPI_Datatype)0x000002eb) - -/* Fortran 1977 Status Size and Indices */ -enum { - MPI_F_STATUS_SIZE = 8, - MPI_F_SOURCE = 0, - MPI_F_TAG = 1, - MPI_F_ERROR = 2 -}; - -/* Fortran 2008 Status Type */ -typedef struct { - MPI_Fint MPI_SOURCE; - MPI_Fint MPI_TAG; - MPI_Fint MPI_ERROR; - MPI_Fint MPI_internal[5]; -} MPI_F08_status; +*/ /* Error Classes */ enum { @@ -575,12 +557,6 @@ typedef void (MPI_T_event_cb_function)(MPI_T_event_instance event_instance, MPI_ typedef void (MPI_T_event_free_cb_function)(MPI_T_event_registration event_registration, MPI_T_cb_safety cb_safety, void *user_data); typedef void (MPI_T_event_dropped_cb_function)(MPI_Count count, MPI_T_event_registration event_registration, int source_index, MPI_T_cb_safety cb_safety, void *user_data); -/* MPI global variables */ -extern MPI_Fint* MPI_F_STATUS_IGNORE; -extern MPI_Fint* MPI_F_STATUSES_IGNORE; -extern MPI_F08_status* MPI_F08_STATUS_IGNORE; -extern MPI_F08_status* MPI_F08_STATUSES_IGNORE; - /* MPI functions */ int MPI_Abort(MPI_Comm comm, int errorcode); int MPI_Accumulate(const void *origin_addr, int origin_count, MPI_Datatype origin_datatype, int target_rank, MPI_Aint target_disp, int target_count, MPI_Datatype target_datatype, MPI_Op op, MPI_Win win); @@ -1167,35 +1143,6 @@ MPI_Aint MPI_Aint_diff(MPI_Aint addr1, MPI_Aint addr2); double MPI_Wtick(void); double MPI_Wtime(void); -int MPI_Status_c2f(const MPI_Status *c_status, MPI_Fint *f_status); -int MPI_Status_f2c(const MPI_Fint *f_status, MPI_Status *c_status); -int MPI_Status_c2f08(const MPI_Status *c_status, MPI_F08_status *f08_status); -int MPI_Status_f082c(const MPI_F08_status *f08_status, MPI_Status *c_status); -int MPI_Status_f2f08(const MPI_Fint *f_status, MPI_F08_status *f08_status); -int MPI_Status_f082f(const MPI_F08_status *f08_status, MPI_Fint *f_status); -MPI_Fint MPI_Comm_c2f(MPI_Comm comm); -MPI_Comm MPI_Comm_f2c(MPI_Fint comm); -MPI_Fint MPI_Errhandler_c2f(MPI_Errhandler errhandler); -MPI_Errhandler MPI_Errhandler_f2c(MPI_Fint errhandler); -MPI_Fint MPI_Type_c2f(MPI_Datatype datatype); -MPI_Datatype MPI_Type_f2c(MPI_Fint datatype); -MPI_Fint MPI_File_c2f(MPI_File file); -MPI_File MPI_File_f2c(MPI_Fint file); -MPI_Fint MPI_Group_c2f(MPI_Group group); -MPI_Group MPI_Group_f2c(MPI_Fint group); -MPI_Fint MPI_Info_c2f(MPI_Info info); -MPI_Info MPI_Info_f2c(MPI_Fint info); -MPI_Fint MPI_Message_c2f(MPI_Message message); -MPI_Message MPI_Message_f2c(MPI_Fint message); -MPI_Fint MPI_Op_c2f(MPI_Op op); -MPI_Op MPI_Op_f2c(MPI_Fint op); -MPI_Fint MPI_Request_c2f(MPI_Request request); -MPI_Request MPI_Request_f2c(MPI_Fint request); -MPI_Fint MPI_Session_c2f(MPI_Session session); -MPI_Session MPI_Session_f2c(MPI_Fint session); -MPI_Fint MPI_Win_c2f(MPI_Win win); -MPI_Win MPI_Win_f2c(MPI_Fint win); - /* MPI_T functions */ int MPI_T_category_changed(int *update_number); int MPI_T_category_get_categories(int cat_index, int len, int indices[]); @@ -1835,35 +1782,6 @@ MPI_Aint PMPI_Aint_diff(MPI_Aint addr1, MPI_Aint addr2); double PMPI_Wtick(void); double PMPI_Wtime(void); -int PMPI_Status_c2f(const MPI_Status *c_status, MPI_Fint *f_status); -int PMPI_Status_f2c(const MPI_Fint *f_status, MPI_Status *c_status); -int PMPI_Status_c2f08(const MPI_Status *c_status, MPI_F08_status *f08_status); -int PMPI_Status_f082c(const MPI_F08_status *f08_status, MPI_Status *c_status); -int PMPI_Status_f2f08(const MPI_Fint *f_status, MPI_F08_status *f08_status); -int PMPI_Status_f082f(const MPI_F08_status *f08_status, MPI_Fint *f_status); -MPI_Fint PMPI_Comm_c2f(MPI_Comm comm); -MPI_Comm PMPI_Comm_f2c(MPI_Fint comm); -MPI_Fint PMPI_Errhandler_c2f(MPI_Errhandler errhandler); -MPI_Errhandler PMPI_Errhandler_f2c(MPI_Fint errhandler); -MPI_Fint PMPI_Type_c2f(MPI_Datatype datatype); -MPI_Datatype PMPI_Type_f2c(MPI_Fint datatype); -MPI_Fint PMPI_File_c2f(MPI_File file); -MPI_File PMPI_File_f2c(MPI_Fint file); -MPI_Fint PMPI_Group_c2f(MPI_Group group); -MPI_Group PMPI_Group_f2c(MPI_Fint group); -MPI_Fint PMPI_Info_c2f(MPI_Info info); -MPI_Info PMPI_Info_f2c(MPI_Fint info); -MPI_Fint PMPI_Message_c2f(MPI_Message message); -MPI_Message PMPI_Message_f2c(MPI_Fint message); -MPI_Fint PMPI_Op_c2f(MPI_Op op); -MPI_Op PMPI_Op_f2c(MPI_Fint op); -MPI_Fint PMPI_Request_c2f(MPI_Request request); -MPI_Request PMPI_Request_f2c(MPI_Fint request); -MPI_Fint PMPI_Session_c2f(MPI_Session session); -MPI_Session PMPI_Session_f2c(MPI_Fint session); -MPI_Fint PMPI_Win_c2f(MPI_Win win); -MPI_Win PMPI_Win_f2c(MPI_Fint win); - /* PMPI_T functions */ int PMPI_T_category_changed(int *update_number); int PMPI_T_category_get_categories(int cat_index, int len, int indices[]); @@ -1917,6 +1835,10 @@ int PMPI_T_source_get_info(int source_index, char *name, int *name_len, char *de int PMPI_T_source_get_num(int *num_sources); int PMPI_T_source_get_timestamp(int source_index, MPI_Count *timestamp); +#ifdef MPI_ABI_FORT +#include "mpi_abi_fort.h" +#endif + #if defined(__cplusplus) } #endif diff --git a/src/binding/abi_fortran/mpi_abi_fort.h b/src/binding/abi_fortran/mpi_abi_fort.h new file mode 100644 index 00000000000..14ecdf307e1 --- /dev/null +++ b/src/binding/abi_fortran/mpi_abi_fort.h @@ -0,0 +1,129 @@ +#ifndef MPI_ABI_FORT_H +#define MPI_ABI_FORT_H + +/* This header includes Fortran-related MPI API. It should be provided by + * an MPI Fortran binding implementation. However, we expect an implementation + * use this exact header. The constants must follow MPI ABI standard. + */ + +/* MPI_Fint must match the Fortran default INTEGER kind. */ +/* It is often equivalent to C int but most compilers support wider options. */ +#if !defined(MPI_ABI_Fint) +#define MPI_ABI_Fint int +#endif +typedef MPI_ABI_Fint MPI_Fint; +#undef MPI_ABI_Fint + +#define MPI_LOGICAL ((MPI_Datatype)0x00000218) +#define MPI_INTEGER ((MPI_Datatype)0x00000219) +#define MPI_REAL ((MPI_Datatype)0x0000021a) +#define MPI_COMPLEX ((MPI_Datatype)0x0000021b) +#define MPI_DOUBLE_PRECISION ((MPI_Datatype)0x0000021c) +#define MPI_DOUBLE_COMPLEX ((MPI_Datatype)0x0000021d) + +#define MPI_2REAL ((MPI_Datatype)0x00000230) +#define MPI_2DOUBLE_PRECISION ((MPI_Datatype)0x00000231) +#define MPI_2INTEGER ((MPI_Datatype)0x00000232) + +#define MPIX_LOGICAL1 ((MPI_Datatype)0x000002c0) +#define MPI_INTEGER1 ((MPI_Datatype)0x000002c1) +#define MPIX_REAL1 ((MPI_Datatype)0x000002c2) +#define MPI_CHARACTER ((MPI_Datatype)0x000002c3) +#define MPIX_LOGICAL2 ((MPI_Datatype)0x000002c8) +#define MPI_INTEGER2 ((MPI_Datatype)0x000002c9) +#define MPI_REAL2 ((MPI_Datatype)0x000002ca) +#define MPIX_LOGICAL4 ((MPI_Datatype)0x000002d0) +#define MPI_INTEGER4 ((MPI_Datatype)0x000002d1) +#define MPI_REAL4 ((MPI_Datatype)0x000002d2) +#define MPI_COMPLEX4 ((MPI_Datatype)0x000002d3) +#define MPIX_LOGICAL8 ((MPI_Datatype)0x000002d8) +#define MPI_INTEGER8 ((MPI_Datatype)0x000002d9) +#define MPI_REAL8 ((MPI_Datatype)0x000002da) +#define MPI_COMPLEX8 ((MPI_Datatype)0x000002db) +#define MPIX_LOGICAL16 ((MPI_Datatype)0x000002e0) +#define MPI_INTEGER16 ((MPI_Datatype)0x000002e1) +#define MPI_REAL16 ((MPI_Datatype)0x000002e2) +#define MPI_COMPLEX16 ((MPI_Datatype)0x000002e3) +#define MPI_COMPLEX32 ((MPI_Datatype)0x000002eb) + +/* Fortran 1977 Status Size and Indices */ +enum { + MPI_F_STATUS_SIZE = 8, + MPI_F_SOURCE = 0, + MPI_F_TAG = 1, + MPI_F_ERROR = 2 +}; + +/* Fortran 2008 Status Type */ +typedef struct { + MPI_Fint MPI_SOURCE; + MPI_Fint MPI_TAG; + MPI_Fint MPI_ERROR; + MPI_Fint MPI_internal[5]; +} MPI_F08_status; + +/* MPI global variables */ +extern MPI_Fint *MPI_F_STATUS_IGNORE; +extern MPI_Fint *MPI_F_STATUSES_IGNORE; +extern MPI_F08_status *MPI_F08_STATUS_IGNORE; +extern MPI_F08_status *MPI_F08_STATUSES_IGNORE; + +int MPI_Status_c2f(const MPI_Status * c_status, MPI_Fint * f_status); +int MPI_Status_f2c(const MPI_Fint * f_status, MPI_Status * c_status); +int MPI_Status_c2f08(const MPI_Status * c_status, MPI_F08_status * f08_status); +int MPI_Status_f082c(const MPI_F08_status * f08_status, MPI_Status * c_status); +int MPI_Status_f2f08(const MPI_Fint * f_status, MPI_F08_status * f08_status); +int MPI_Status_f082f(const MPI_F08_status * f08_status, MPI_Fint * f_status); +MPI_Fint MPI_Comm_c2f(MPI_Comm comm); +MPI_Comm MPI_Comm_f2c(MPI_Fint comm); +MPI_Fint MPI_Errhandler_c2f(MPI_Errhandler errhandler); +MPI_Errhandler MPI_Errhandler_f2c(MPI_Fint errhandler); +MPI_Fint MPI_Type_c2f(MPI_Datatype datatype); +MPI_Datatype MPI_Type_f2c(MPI_Fint datatype); +MPI_Fint MPI_File_c2f(MPI_File file); +MPI_File MPI_File_f2c(MPI_Fint file); +MPI_Fint MPI_Group_c2f(MPI_Group group); +MPI_Group MPI_Group_f2c(MPI_Fint group); +MPI_Fint MPI_Info_c2f(MPI_Info info); +MPI_Info MPI_Info_f2c(MPI_Fint info); +MPI_Fint MPI_Message_c2f(MPI_Message message); +MPI_Message MPI_Message_f2c(MPI_Fint message); +MPI_Fint MPI_Op_c2f(MPI_Op op); +MPI_Op MPI_Op_f2c(MPI_Fint op); +MPI_Fint MPI_Request_c2f(MPI_Request request); +MPI_Request MPI_Request_f2c(MPI_Fint request); +MPI_Fint MPI_Session_c2f(MPI_Session session); +MPI_Session MPI_Session_f2c(MPI_Fint session); +MPI_Fint MPI_Win_c2f(MPI_Win win); +MPI_Win MPI_Win_f2c(MPI_Fint win); + +int PMPI_Status_c2f(const MPI_Status * c_status, MPI_Fint * f_status); +int PMPI_Status_f2c(const MPI_Fint * f_status, MPI_Status * c_status); +int PMPI_Status_c2f08(const MPI_Status * c_status, MPI_F08_status * f08_status); +int PMPI_Status_f082c(const MPI_F08_status * f08_status, MPI_Status * c_status); +int PMPI_Status_f2f08(const MPI_Fint * f_status, MPI_F08_status * f08_status); +int PMPI_Status_f082f(const MPI_F08_status * f08_status, MPI_Fint * f_status); +MPI_Fint PMPI_Comm_c2f(MPI_Comm comm); +MPI_Comm PMPI_Comm_f2c(MPI_Fint comm); +MPI_Fint PMPI_Errhandler_c2f(MPI_Errhandler errhandler); +MPI_Errhandler PMPI_Errhandler_f2c(MPI_Fint errhandler); +MPI_Fint PMPI_Type_c2f(MPI_Datatype datatype); +MPI_Datatype PMPI_Type_f2c(MPI_Fint datatype); +MPI_Fint PMPI_File_c2f(MPI_File file); +MPI_File PMPI_File_f2c(MPI_Fint file); +MPI_Fint PMPI_Group_c2f(MPI_Group group); +MPI_Group PMPI_Group_f2c(MPI_Fint group); +MPI_Fint PMPI_Info_c2f(MPI_Info info); +MPI_Info PMPI_Info_f2c(MPI_Fint info); +MPI_Fint PMPI_Message_c2f(MPI_Message message); +MPI_Message PMPI_Message_f2c(MPI_Fint message); +MPI_Fint PMPI_Op_c2f(MPI_Op op); +MPI_Op PMPI_Op_f2c(MPI_Fint op); +MPI_Fint PMPI_Request_c2f(MPI_Request request); +MPI_Request PMPI_Request_f2c(MPI_Fint request); +MPI_Fint PMPI_Session_c2f(MPI_Session session); +MPI_Session PMPI_Session_f2c(MPI_Fint session); +MPI_Fint PMPI_Win_c2f(MPI_Win win); +MPI_Win PMPI_Win_f2c(MPI_Fint win); + +#endif /* MPI_ABI_FORT_H */ From 62c4812d7ec012eccb5ddc29a59948fcbc78bf47 Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Fri, 29 Mar 2024 16:15:39 -0500 Subject: [PATCH 2/8] abi: build libmpi_abi.so without Fortran parts Skip MPI_Fint, _{f2c,c2f,f2f08,f082f,c2f08,f082c}, MPI_{F,F08}_STATUS(ES)_IGNORE etc. --- maint/gen_abi.py | 9 ++++++++- maint/gen_binding_c.py | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/maint/gen_abi.py b/maint/gen_abi.py index f7e163b2ebf..14ef3610a7e 100644 --- a/maint/gen_abi.py +++ b/maint/gen_abi.py @@ -37,7 +37,7 @@ def dump_mpi_abi_internal_h(mpi_abi_internal_h): def gen_mpi_abi_internal_h(out): re_Handle = r'\bMPI_(Comm|Datatype|Errhandler|Group|Info|Message|Op|Request|Session|Win|KEYVAL_INVALID|TAG_UB|IO|HOST|WTIME_IS_GLOBAL|APPNUM|LASTUSEDCODE|UNIVERSE_SIZE|WIN_BASE|WIN_DISP_UNIT|WIN_SIZE|WIN_CREATE_FLAVOR|WIN_MODEL)\b' for line in G.abi_h_lines: - if RE.search(r'MPI_ABI_H_INCLUDED', line): + if RE.search(r'MPI_ABI_H_INCLUDED|MPI_H_ABI', line): # skip the include guard, harmless pass elif RE.match(r'\s*int MPI_(SOURCE|TAG|ERROR);', line): @@ -100,6 +100,13 @@ def gen_mpi_abi_internal_h(out): print("#define MPI_ABI_INTERNAL_H_INCLUDED", file=Out) print("", file=Out) + # the internal code use MPI_Fint etc. Temporary until ABI proposal settles and MPICH implementation cleans up. + # TODO: skip src/mpi/misc/f2c_impl.c + print("typedef int MPI_Fint;", file=Out) + print("typedef struct {MPI_Fint MPI_SOURCE,MPI_TAG,MPI_ERROR,count_lo,count_hi_and_cancelled,dummy[3];} MPI_F08_status;", file=Out) + print("extern MPI_Fint *MPI_F_STATUS_IGNORE, *MPI_F_STATUSES_IGNORE;", file=Out); + print("extern MPI_F08_status *MPI_F08_STATUS_IGNORE, *MPI_F08_STATUSES_IGNORE;", file=Out); + for k in define_constants: print("#define %s %s" % (k, define_constants[k]), file=Out) print("", file=Out) diff --git a/maint/gen_binding_c.py b/maint/gen_binding_c.py index be41c014dd3..ff90086c104 100644 --- a/maint/gen_binding_c.py +++ b/maint/gen_binding_c.py @@ -123,6 +123,10 @@ def dump_func_abi(func): if 'replace' in func and 'body' not in func: continue + # skip Fortran inter op functions + if re.match(r'.*_(f2c|c2f|f2f08|f082f|f082c|c2f08)', func['name']): + continue + if re.match(r'MPIX_', func['name']): if re.match(r'MPIX_(Grequest_|Type_iov)', func['name']): # needed by ROMIO From 90a732fd7202c339931e4e1987d556a247662aff Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Tue, 2 Apr 2024 15:18:01 -0500 Subject: [PATCH 3/8] python: add custom_dir to load_C_func_list Add an option so different bindings can selectively choose to whether to only load function defined in the custom_dir or all functions listed in the binding_dir. --- maint/local_python/mpi_api.py | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/maint/local_python/mpi_api.py b/maint/local_python/mpi_api.py index 73c0364efe1..53c82cf5a53 100644 --- a/maint/local_python/mpi_api.py +++ b/maint/local_python/mpi_api.py @@ -12,7 +12,7 @@ import os import glob -def load_C_func_list(binding_dir="src/binding", silent=False): +def load_C_func_list(binding_dir="src/binding", silent=False, custom_dir="src/binding/c"): # -- Loading Standard APIs -- if os.path.exists("%s/apis.json" % binding_dir): if not silent: print("Loading %s/apis.json ..." % binding_dir) @@ -26,16 +26,16 @@ def load_C_func_list(binding_dir="src/binding", silent=False): if not silent: print("Loading %s/custom_mapping.txt ..." % binding_dir) load_mpi_mapping("%s/custom_mapping.txt" % binding_dir) - # -- Loading MPICH APIs -- - - api_files = glob.glob("%s/c/*_api.txt" % binding_dir) - for f in api_files: - if RE.match(r'.*\/(\w+)_api.txt', f): - # The name in eg pt2pt_api.txt indicates the output folder. - # Only the api functions with output folder will get generated. - # This allows simple control of what functions to generate. - if not silent: print("Loading %s ..." % f) - load_mpi_api(f, RE.m.group(1)) + if custom_dir: + # -- Loading MPICH APIs -- + api_files = glob.glob("%s/*_api.txt" % custom_dir) + for f in api_files: + if RE.match(r'.*\/(\w+)_api.txt', f): + # The name in eg pt2pt_api.txt indicates the output folder. + # Only the api functions with output folder will get generated. + # This allows simple control of what functions to generate. + if not silent: print("Loading %s ..." % f) + load_mpi_api(f, RE.m.group(1)) # -- filter and sort func_list -- func_list = [] @@ -45,11 +45,13 @@ def load_C_func_list(binding_dir="src/binding", silent=False): elif RE.match(r'\w+_(function|FN)$', f['name']): # skip various callback functions continue - elif not 'dir' in f: + elif custom_dir and not 'dir' in f: if not silent: print(" skip %s (not defined)" % f['name']) else: func_list.append(f) - func_list.sort(key = lambda f: f['dir']) + + if custom_dir: + func_list.sort(key = lambda f: f['dir']) load_mpix_txt("%s/mpix.txt" % binding_dir) From b835e25c99095bb03cf8c0f5898a8ebdb5c02660 Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Wed, 27 Mar 2024 23:38:43 -0500 Subject: [PATCH 4/8] abi_fortran: copy fortran binding files Start from a duplicate copy. We'll refactor later. Or, if things work out, the ABI fortran binding will be the only binding we need. --- src/binding/abi_fortran/mpif_h/Makefile.mk | 48 +++ src/binding/abi_fortran/mpif_h/attr_proxy.c | 45 ++ src/binding/abi_fortran/mpif_h/fdebug.c | 178 ++++++++ src/binding/abi_fortran/mpif_h/mpi_fortimpl.h | 389 ++++++++++++++++++ src/binding/abi_fortran/mpif_h/setbot.c.in | 207 ++++++++++ src/binding/abi_fortran/mpif_h/setbotf.f.in | 29 ++ src/binding/abi_fortran/use_mpi/Makefile.mk | 261 ++++++++++++ src/binding/abi_fortran/use_mpi/mpi.f90 | 9 + .../abi_fortran/use_mpi_f08/Makefile.mk | 333 +++++++++++++++ .../use_mpi_f08/mpi_c_interface.f90 | 11 + .../use_mpi_f08/mpi_c_interface_glue.f90 | 92 +++++ .../use_mpi_f08/mpi_c_interface_types.f90.in | 59 +++ .../use_mpi_f08/mpi_f08_callbacks.f90 | 349 ++++++++++++++++ .../use_mpi_f08/mpi_f08_link_constants.f90 | 140 +++++++ .../use_mpi_f08/wrappers_c/cdesc.c | 107 +++++ .../use_mpi_f08/wrappers_c/cdesc.h | 45 ++ .../use_mpi_f08/wrappers_c/comm_spawn_c.c | 35 ++ .../wrappers_c/comm_spawn_multiple_c.c | 129 ++++++ .../use_mpi_f08/wrappers_c/utils.c | 138 +++++++ 19 files changed, 2604 insertions(+) create mode 100644 src/binding/abi_fortran/mpif_h/Makefile.mk create mode 100644 src/binding/abi_fortran/mpif_h/attr_proxy.c create mode 100644 src/binding/abi_fortran/mpif_h/fdebug.c create mode 100644 src/binding/abi_fortran/mpif_h/mpi_fortimpl.h create mode 100644 src/binding/abi_fortran/mpif_h/setbot.c.in create mode 100644 src/binding/abi_fortran/mpif_h/setbotf.f.in create mode 100644 src/binding/abi_fortran/use_mpi/Makefile.mk create mode 100644 src/binding/abi_fortran/use_mpi/mpi.f90 create mode 100644 src/binding/abi_fortran/use_mpi_f08/Makefile.mk create mode 100644 src/binding/abi_fortran/use_mpi_f08/mpi_c_interface.f90 create mode 100644 src/binding/abi_fortran/use_mpi_f08/mpi_c_interface_glue.f90 create mode 100644 src/binding/abi_fortran/use_mpi_f08/mpi_c_interface_types.f90.in create mode 100644 src/binding/abi_fortran/use_mpi_f08/mpi_f08_callbacks.f90 create mode 100644 src/binding/abi_fortran/use_mpi_f08/mpi_f08_link_constants.f90 create mode 100644 src/binding/abi_fortran/use_mpi_f08/wrappers_c/cdesc.c create mode 100644 src/binding/abi_fortran/use_mpi_f08/wrappers_c/cdesc.h create mode 100644 src/binding/abi_fortran/use_mpi_f08/wrappers_c/comm_spawn_c.c create mode 100644 src/binding/abi_fortran/use_mpi_f08/wrappers_c/comm_spawn_multiple_c.c create mode 100644 src/binding/abi_fortran/use_mpi_f08/wrappers_c/utils.c diff --git a/src/binding/abi_fortran/mpif_h/Makefile.mk b/src/binding/abi_fortran/mpif_h/Makefile.mk new file mode 100644 index 00000000000..a7d02ecb84d --- /dev/null +++ b/src/binding/abi_fortran/mpif_h/Makefile.mk @@ -0,0 +1,48 @@ +## +## Copyright (C) by Argonne National Laboratory +## See COPYRIGHT in top-level directory +## + +f77_cppflags = $(AM_CPPFLAGS) -I${main_top_srcdir}/src/binding/fortran/mpif_h + +if BUILD_F77_BINDING + +mpifort_convenience_libs += lib/libf77_mpi.la +noinst_LTLIBRARIES += lib/libf77_mpi.la + +lib_libf77_mpi_la_SOURCES = \ + src/binding/fortran/mpif_h/fortran_binding.c \ + src/binding/fortran/mpif_h/attr_proxy.c \ + src/binding/fortran/mpif_h/fdebug.c \ + src/binding/fortran/mpif_h/setbot.c \ + src/binding/fortran/mpif_h/setbotf.f + +lib_libf77_mpi_la_CPPFLAGS = $(f77_cppflags) + +if BUILD_PROFILING_LIB +mpifort_convenience_libs += lib/libf77_pmpi.la +noinst_LTLIBRARIES += lib/libf77_pmpi.la + +lib_libf77_pmpi_la_SOURCES = src/binding/fortran/mpif_h/fortran_binding.c + +# build "pmpi_xxx_" f77 public functions +lib_libf77_pmpi_la_CPPFLAGS = $(f77_cppflags) -DF77_USE_PMPI + +# build "mpi_xxx_" f77 public functions +lib_libf77_mpi_la_CPPFLAGS += -DMPICH_MPI_FROM_PMPI -DUSE_ONLY_MPI_NAMES +endif BUILD_PROFILING_LIB + +noinst_HEADERS += \ + src/binding/fortran/mpif_h/fortran_profile.h \ + src/binding/fortran/mpif_h/mpi_fortimpl.h + +# config.status copies src/binding/fortran/mpif_h/mpif.h to src/include (see the relevant +# AC_CONFIG_COMMANDS in configure.ac), so we need to delete it at distclean time +# too. More work is needed in this Makefile.mk to keep src/include/mpif.h up to +# date w.r.t. the src/binding/fortran/mpif_h version. +DISTCLEANFILES += src/binding/fortran/mpif_h/mpif.h src/include/mpif.h +nodist_include_HEADERS += src/binding/fortran/mpif_h/mpif.h + + +endif BUILD_F77_BINDING + diff --git a/src/binding/abi_fortran/mpif_h/attr_proxy.c b/src/binding/abi_fortran/mpif_h/attr_proxy.c new file mode 100644 index 00000000000..38e42012283 --- /dev/null +++ b/src/binding/abi_fortran/mpif_h/attr_proxy.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +#include "mpi_fortimpl.h" + +static int MPII_copy_attr_f90_proxy(MPI_Comm_copy_attr_function * user_function, int handle, + int keyval, void *extra_state, MPIR_Attr_type value_type, + void *value, void **new_value, int *flag) +{ + MPI_Fint ierr = 0; + MPI_Fint fhandle = (MPI_Fint) handle; + MPI_Fint fkeyval = (MPI_Fint) keyval; + MPI_Aint fvalue = (MPI_Aint) value; + MPI_Aint *fextra = (MPI_Aint *) extra_state; + MPI_Aint fnew = 0; + MPI_Fint fflag = 0; + + ((F90_CopyFunction *) (void *) user_function) (&fhandle, &fkeyval, fextra, &fvalue, &fnew, + &fflag, &ierr); + + *flag = MPII_FROM_FLOG(fflag); + *new_value = (void *) fnew; + return (int) ierr; +} + +static int MPII_delete_attr_f90_proxy(MPI_Comm_delete_attr_function * user_function, int handle, + int keyval, MPIR_Attr_type value_type, void *value, + void *extra_state) +{ + MPI_Fint ierr = 0; + MPI_Fint fhandle = (MPI_Fint) handle; + MPI_Fint fkeyval = (MPI_Fint) keyval; + MPI_Aint fvalue = (MPI_Aint) value; + MPI_Aint *fextra = (MPI_Aint *) extra_state; + + ((F90_DeleteFunction *) (void *) user_function) (&fhandle, &fkeyval, &fvalue, fextra, &ierr); + return (int) ierr; +} + +void MPII_Keyval_set_f90_proxy(int keyval) +{ + MPII_Keyval_set_proxy(keyval, MPII_copy_attr_f90_proxy, MPII_delete_attr_f90_proxy); +} diff --git a/src/binding/abi_fortran/mpif_h/fdebug.c b/src/binding/abi_fortran/mpif_h/fdebug.c new file mode 100644 index 00000000000..57078c39592 --- /dev/null +++ b/src/binding/abi_fortran/mpif_h/fdebug.c @@ -0,0 +1,178 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +/* style: allow:fprintf:21 sig:0 */ + +#include "mpi_fortimpl.h" + +#if defined(HAVE_PRAGMA_WEAK) && defined(HAVE_MULTIPLE_PRAGMA_WEAK) +void mpir_is_bottom_(void *a, int *ierr); +void mpir_is_in_place_(void *a, int *ierr); +/* FIXME probably MPI_WEIGHTS_EMPTY needs support somewhere in this file */ +void mpir_is_unweighted_(void *a, int *ierr); +void mpir_is_status_ignore_(void *a, int *ierr); +void mpir_is_statuses_ignore_(void *a, int *ierr); +void mpir_is_errcodes_ignore_(void *a, int *ierr); +void mpir_is_argvs_null_(void *a, int *ierr); + +extern void MPIR_IS_BOTTOM(void *a, int *ierr); +extern void mpir_is_bottom(void *a, int *ierr); +extern void mpir_is_bottom__(void *a, int *ierr); +extern void MPIR_IS_IN_PLACE(void *a, int *ierr); +extern void mpir_is_in_place(void *a, int *ierr); +extern void mpir_is_in_place__(void *a, int *ierr); +extern void MPIR_IS_UNWEIGHTED(void *a, int *ierr); +extern void mpir_is_unweighted(void *a, int *ierr); +extern void mpir_is_unweighted__(void *a, int *ierr); +extern void MPIR_IS_STATUS_IGNORE(void *a, int *ierr); +extern void mpir_is_status_ignore(void *a, int *ierr); +extern void mpir_is_status_ignore__(void *a, int *ierr); +extern void MPIR_IS_STATUSES_IGNORE(void *a, int *ierr); +extern void mpir_is_statuses_ignore(void *a, int *ierr); +extern void mpir_is_statuses_ignore__(void *a, int *ierr); +extern void MPIR_IS_ERRCODES_IGNORE(void *a, int *ierr); +extern void mpir_is_errcodes_ignore(void *a, int *ierr); +extern void mpir_is_errcodes_ignore__(void *a, int *ierr); +extern void MPIR_IS_ARGVS_NULL(void *a, int *ierr); +extern void mpir_is_argvs_null(void *a, int *ierr); +extern void mpir_is_argvs_null__(void *a, int *ierr); + +#pragma weak MPIR_IS_BOTTOM = mpir_is_bottom_ +#pragma weak mpir_is_bottom = mpir_is_bottom_ +#pragma weak mpir_is_bottom__ = mpir_is_bottom_ +#pragma weak MPIR_IS_IN_PLACE = mpir_is_in_place_ +#pragma weak mpir_is_in_place = mpir_is_in_place_ +#pragma weak mpir_is_in_place__ = mpir_is_in_place_ +#pragma weak MPIR_IS_UNWEIGHTED = mpir_is_unweighted_ +#pragma weak mpir_is_unweighted = mpir_is_unweighted_ +#pragma weak mpir_is_unweighted__ = mpir_is_unweighted_ +#pragma weak MPIR_IS_STATUS_IGNORE = mpir_is_status_ignore_ +#pragma weak mpir_is_status_ignore = mpir_is_status_ignore_ +#pragma weak mpir_is_status_ignore__ = mpir_is_status_ignore_ +#pragma weak MPIR_IS_STATUSES_IGNORE = mpir_is_statuses_ignore_ +#pragma weak mpir_is_statuses_ignore = mpir_is_statuses_ignore_ +#pragma weak mpir_is_statuses_ignore__ = mpir_is_statuses_ignore_ +#pragma weak MPIR_IS_ERRCODES_IGNORE = mpir_is_errcodes_ignore_ +#pragma weak mpir_is_errcodes_ignore = mpir_is_errcodes_ignore_ +#pragma weak mpir_is_errcodes_ignore__ = mpir_is_errcodes_ignore_ +#pragma weak MPIR_IS_ARGVS_NULL = mpir_is_argvs_null_ +#pragma weak mpir_is_argvs_null = mpir_is_argvs_null_ +#pragma weak mpir_is_argvs_null__ = mpir_is_argvs_null_ +#else +#if defined(F77_NAME_UPPER) +#define mpir_is_bottom_ MPIR_IS_BOTTOM +#define mpir_is_in_place_ MPIR_IS_IN_PLACE +#define mpir_is_unweighted_ MPIR_IS_UNWEIGHTED +#define mpir_is_status_ignore_ MPIR_IS_STATUS_IGNORE +#define mpir_is_statuses_ignore_ MPIR_IS_STATUSES_IGNORE +#define mpir_is_errcodes_ignore_ MPIR_IS_ERRCODES_IGNORE +#define mpir_is_argvs_null_ MPIR_IS_ARGVS_NULL +#elif defined(F77_NAME_LOWER_2USCORE) +#define mpir_is_bottom_ mpir_is_bottom__ +#define mpir_is_in_place_ mpir_is_in_place__ +#define mpir_is_unweighted_ mpir_is_unweighted__ +#define mpir_is_status_ignore_ mpir_is_status_ignore__ +#define mpir_is_statuses_ignore_ mpir_is_statuses_ignore__ +#define mpir_is_errcodes_ignore_ mpir_is_errcodes_ignore__ +#define mpir_is_argvs_null_ mpir_is_argvs_null__ +#elif defined(F77_NAME_LOWER) +#define mpir_is_bottom_ mpir_is_bottom +#define mpir_is_in_place_ mpir_is_in_place +#define mpir_is_unweighted_ mpir_is_unweighted +#define mpir_is_status_ignore_ mpir_is_status_ignore +#define mpir_is_statuses_ignore_ mpir_is_statuses_ignore +#define mpir_is_errcodes_ignore_ mpir_is_errcodes_ignore +#define mpir_is_argvs_null_ mpir_is_argvs_null +#endif + +void mpir_is_bottom_(void *a, int *ierr); +void mpir_is_in_place_(void *a, int *ierr); +void mpir_is_unweighted_(void *a, int *ierr); +void mpir_is_status_ignore_(void *a, int *ierr); +void mpir_is_statuses_ignore_(void *a, int *ierr); +void mpir_is_errcodes_ignore_(void *a, int *ierr); +void mpir_is_argvs_null_(void *a, int *ierr); + +#endif + +#include + +/* --BEGIN DEBUG-- */ +/* + Define Fortran functions MPIR_IS_() that are callable in Fortran + to check if the Fortran constants, MPI_, are recognized by the MPI + implementation (in C library). +*/ +void mpir_is_bottom_(void *a, int *ierr) +{ + *ierr = (a == MPIR_F_MPI_BOTTOM ? 1 : 0); + if (*ierr) + fprintf(stderr, "Matched : "); + else + fprintf(stderr, "Not matched : "); + fprintf(stderr, "MPIR_F_MPI_BOTTOM=%p, MPI_BOTTOM=%p\n", MPIR_F_MPI_BOTTOM, a); +} + +void mpir_is_in_place_(void *a, int *ierr) +{ + *ierr = (a == MPIR_F_MPI_IN_PLACE ? 1 : 0); + if (*ierr) + fprintf(stderr, "Matched : "); + else + fprintf(stderr, "Not matched : "); + fprintf(stderr, "MPIR_F_MPI_IN_PLACE=%p, MPI_IN_PLACE=%p\n", MPIR_F_MPI_IN_PLACE, a); +} + +void mpir_is_unweighted_(void *a, int *ierr) +{ + *ierr = (a == MPIR_F_MPI_UNWEIGHTED ? 1 : 0); + if (*ierr) + fprintf(stderr, "Matched : "); + else + fprintf(stderr, "Not matched : "); + fprintf(stderr, "MPIR_F_MPI_UNWEIGHTED=%p, MPI_UNWEIGHTED=%p\n", MPIR_F_MPI_UNWEIGHTED, a); +} + +void mpir_is_status_ignore_(void *a, int *ierr) +{ + *ierr = (a == MPI_F_STATUS_IGNORE ? 1 : 0); + if (*ierr) + fprintf(stderr, "Matched : "); + else + fprintf(stderr, "Not matched : "); + fprintf(stderr, "MPI_F_STATUS_IGNORE=%p, MPI_STATUS_IGNORE=%p\n", MPI_F_STATUS_IGNORE, a); +} + +void mpir_is_statuses_ignore_(void *a, int *ierr) +{ + *ierr = (a == MPI_F_STATUSES_IGNORE ? 1 : 0); + if (*ierr) + fprintf(stderr, "Matched : "); + else + fprintf(stderr, "Not matched : "); + fprintf(stderr, "MPI_F_STATUSES_IGNORE=%p, MPI_STATUSES_IGNORE=%p\n", MPI_F_STATUSES_IGNORE, a); +} + +void mpir_is_errcodes_ignore_(void *a, int *ierr) +{ + *ierr = (a == MPI_F_ERRCODES_IGNORE ? 1 : 0); + if (*ierr) + fprintf(stderr, "Matched : "); + else + fprintf(stderr, "Not matched : "); + fprintf(stderr, "MPI_F_ERRCODES_IGNORE=%p, MPI_ERRCODES_IGNORE=%p\n", MPI_F_ERRCODES_IGNORE, a); +} + +void mpir_is_argvs_null_(void *a, int *ierr) +{ + *ierr = (a == MPI_F_ARGVS_NULL ? 1 : 0); + if (*ierr) + fprintf(stderr, "Matched : "); + else + fprintf(stderr, "Not matched : "); + fprintf(stderr, "MPI_F_ARGVS_NULL=%p, MPI_ARGVS_NULL=%p\n", MPI_F_ARGVS_NULL, a); +} + +/* --END DEBUG-- */ diff --git a/src/binding/abi_fortran/mpif_h/mpi_fortimpl.h b/src/binding/abi_fortran/mpif_h/mpi_fortimpl.h new file mode 100644 index 00000000000..bad20364178 --- /dev/null +++ b/src/binding/abi_fortran/mpif_h/mpi_fortimpl.h @@ -0,0 +1,389 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +#ifndef MPI_FORTIMPL_H_INCLUDED +#define MPI_FORTIMPL_H_INCLUDED + +#include "mpichconf.h" +#include "mpi.h" +#include "mpir_attr_generic.h" +#include "mpii_f77interface.h" +#include /* for ssize_t */ +#include +#include +#include + +/* Handle different mechanisms for passing Fortran CHARACTER to routines. + * + * In the case where MPI_Fint is a different size from int, it appears that + * compilers use an int, rather than an MPI_Fint, for the length. However, + * there is no standard for this, so some compiler may choose to use + * an MPI_Fint instead of an int. In that case, we will need an additional + * case. + */ +/* + * Many Fortran compilers at some point changed from passing the length of + * a CHARACTER*(N) in an int to using a size_t. This definition allows + * us to select either size_t or int. Determining which one the compiler + * is using may require reading the documentation or examining the generated + * code. + * + * The default is left as "int" because that is the correct legacy choice. + * Configure may need to check the compiler vendor and version to decide + * whether to select size_t. And despite documentation to the contrary, + * in our experiments, gfortran used int instead of size_t, which was + * verified by inspecting the assembly code. + */ +#ifdef USE_FORT_STR_LEN_SIZET +#define FORT_SIZE_INT size_t +#else +#define FORT_SIZE_INT int +#endif + +#ifdef USE_FORT_MIXED_STR_LEN +#define FORT_MIXED_LEN_DECL , FORT_SIZE_INT +#define FORT_END_LEN_DECL +#define FORT_MIXED_LEN(a) , FORT_SIZE_INT a +#define FORT_END_LEN(a) +#else +#define FORT_MIXED_LEN_DECL +#define FORT_END_LEN_DECL , FORT_SIZE_INT +#define FORT_MIXED_LEN(a) +#define FORT_END_LEN(a) , FORT_SIZE_INT a +#endif + +/* NOTE: both leading and trailing spaces are not counted */ +static inline int get_fort_str_len(char *s, int len) +{ + char *p = s + len - 1; + while (*p == ' ' && p > s) { + p--; + } + while (s < p && *s == ' ') { + s++; + } + + if (p == s && *s == ' ') { + return 0; + } else { + return (int) (p + 1 - s); + } +} + +/* NOTE: n is returned from get_fort_str_len. + * s may include leading spaces that will be removed. + */ +static inline void copy_fort_str_to_c(char *c_str, char *s, int n) +{ + if (n > 0) { + while (*s == ' ') { + s++; + } + memcpy(c_str, s, n); + } + c_str[n] = '\0'; +} + +/* duplicate fortran string to a C string */ +static inline char *MPIR_fort_dup_str(char *s, int len) +{ + int n = get_fort_str_len(s, len); + char *c_str = (char *) malloc(n + 1); + copy_fort_str_to_c(c_str, s, n); + + return c_str; +} + +/* duplicate fortran string array (e.g. argv in MPI_Comm_spawn) + * + * If count > 0, we have count strings, e.g. array_of_commands. + * Otherwise, the array is terminated by an empty/NULL string. + * + * When we assume the array is NULL terminated, user mistakes can easily become + * undefined behavior. But I guess that is not much we can do. + */ +static inline char **MPIR_fort_dup_str_array(char *s, int len, int stride, int count) +{ + int num_strs; + + if (count > 0) { + num_strs = count; + } else { + /* Compute the size of the array by looking for an all-blank line */ + num_strs = 0; + char *p = s; + while (1) { + int n = get_fort_str_len(p, len); + if (n == 0) { + break; + } + num_strs++; + p += stride; + } + count = num_strs; + /* add terminating string */ + num_strs++; + } + + char **strs = (char **) malloc(num_strs * sizeof(char *)); + + if (count > 0) { + char *str = (char *) malloc(num_strs * (len + 1)); + + for (int i = 0; i < count; i++) { + char *p1 = s + i * stride; + char *p2 = str + i * (len + 1); + + int n = get_fort_str_len(p1, len); + copy_fort_str_to_c(p2, p1, n); + + strs[i] = p2; + } + } + + if (num_strs > count) { + /* Null terminate the array */ + strs[count] = NULL; + } + + return strs; +} + +static inline void MPIR_fort_free_str_array(char **strs) +{ + if (strs[0]) { + free(strs[0]); + } + free(strs); +} + +/* duplicate fortran string 2d array (e.g. array_of_argv in MPI_Comm_spawn_multiple) */ +static inline char ***MPIR_fort_dup_str_2d_array(char *s, int len, int count) +{ + char ***str_2d_array = malloc(count * sizeof(char **)); + for (int k = 0; k < count; k++) { + char *p = s + k * len; /* NOTE: column-major */ + + str_2d_array[k] = MPIR_fort_dup_str_array(p, len, count * len, 0); + } + + return str_2d_array; +} + +static inline void MPIR_fort_free_str_2d_array(char ***str_2d_array, int count) +{ + for (int i = 0; i < count; i++) { + MPIR_fort_free_str_array(str_2d_array[i]); + } + free(str_2d_array); +} + +static inline void MPIR_fort_copy_str_from_c(char *s, int len, char *c_str) +{ + int n = strlen(c_str); + if (n > len) { + n = len; + } + + memcpy(s, c_str, n); + for (int i = n; i < len; i++) { + s[i] = ' '; + } +} + +/* ------------------------------------------------------------------------- */ +/* The following definitions are used to support the Microsoft compilers + + The following C preprocessor macros are not discoved by configure. + Instead, they must be defined separately; this is normally done as part of + the Windows-specific configuration process. + + USE_FORT_STDCALL - Use __stdcall for the calling convention + USE_FORT_CDECL - Use __cdelc for the calling convention + These define the macro FORT_CALL ; for other systems, FORT_CALL is + empty + + Note: It may be that these should be USE_MSC_xxx to indicate that + these can only be used with the MS C compiler. + + USE_MSC_DLLSPEC - Use __declspec to control the import or export of + symbols in a generated dynamic link library (DLL) + This defines the macros FORT_DECL_SPEC and FORT_C_DECL_SPEC ; for + other systems, these names both expand to empty + If USE_MSC_DLLSPEC is defined, then the macros FORTRAN_EXPORTS and + FORTRAN_FROM_C_EXPORTS controls whether dllexport or dllimport is + specified. + + The name (USE_MSC_xxx) here indicates that the MS C compiler is + required for this. + + */ + +/* Support Windows extension to specify calling convention */ +#ifdef USE_FORT_CDECL +#define FORT_CALL __cdecl +#elif defined (USE_FORT_STDCALL) +#define FORT_CALL __stdcall +#else +#define FORT_CALL +#endif + +/* Support Windows extension to specify which functions are exported from + shared (DLL) libraries */ +/* Backward compatibility (was HAVE_FORTRAN_API) */ +#if defined(HAVE_FORTRAN_API) && !defined(USE_MSC_DLLSPEC) +#define USE_MSC_DLLSPEC +#endif + +#ifdef USE_MSC_DLLSPEC +#ifdef FORTRAN_EXPORTS +#define FORT_DLL_SPEC __declspec(dllexport) +#else +#define FORT_DLL_SPEC __declspec(dllimport) +#endif +#else +#define FORT_DLL_SPEC MPICH_API_PUBLIC +#endif + + +/* ------------------------------------------------------------------------- */ + +/* Support an alternate approach for declaring a weak symbol supported by + some versions of gcc */ +#ifdef USE_WEAK_ATTRIBUTE +#define FUNC_ATTRIBUTES(name) __attribute__ ((weak,alias(#name))) +#else +#define FUNC_ATTRIBUTES(name) +#endif + +/* ------------------------------------------------------------------------- */ + +/* If there is no MPI I/O support, and we are still using MPIO_Request, + make sure that one is defined */ +#ifndef MPIO_REQUEST_DEFINED +#define MPIO_Request MPI_Request +#endif + +/* MPI_FAint is used as the C type corresponding to the Fortran type + used for addresses. For now, we make this the same as MPI_Aint. + Note that since this is defined only for this private include file, + we can get away with calling MPI_xxx */ +typedef MPI_Aint MPI_FAint; + +/* Utility functions */ + +/* Define the internal values needed for Fortran support */ + +/* Fortran logicals */ +/* The definitions for the Fortran logical values are also needed + by the reduction operations in mpi/coll/opland, oplor, and oplxor, + so they are defined in src/include/mpii_fortlogical.h */ +#include "mpii_fortlogical.h" + + +/* MPIR_F_MPI_BOTTOM is the address of the Fortran MPI_BOTTOM value */ +extern FORT_DLL_SPEC int MPIR_F_NeedInit; +extern FORT_DLL_SPEC void *MPIR_F_MPI_BOTTOM; +extern FORT_DLL_SPEC void *MPIR_F_MPI_IN_PLACE; +extern FORT_DLL_SPEC void *MPIR_F_MPI_BUFFER_AUTOMATIC; +extern FORT_DLL_SPEC void *MPIR_F_MPI_UNWEIGHTED; +extern FORT_DLL_SPEC void *MPIR_F_MPI_WEIGHTS_EMPTY; +/* MPI_F_STATUS(ES)_IGNORE are defined in mpi.h and are intended for C + programs. */ +/* +extern FORT_DLL_SPEC MPI_Fint *MPI_F_STATUS_IGNORE; +extern FORT_DLL_SPEC MPI_Fint *MPI_F_STATUSES_IGNORE; +*/ +/* MPI_F_ERRCODES_IGNORE is defined as a Fortran INTEGER type, so must + be declared as MPI_Fint */ +extern FORT_DLL_SPEC MPI_Fint *MPI_F_ERRCODES_IGNORE; +extern FORT_DLL_SPEC void *MPI_F_ARGV_NULL; +extern FORT_DLL_SPEC void *MPI_F_ARGVS_NULL; +/* MPIR_F_PTR checks for the Fortran MPI_BOTTOM and provides the value + MPI_BOTTOM if found + See src/pt2pt/addressf.c for why MPIR_F_PTR(a) is just (a) +*/ +/* #define MPIR_F_PTR(a) (((a)==(MPIR_F_MPI_BOTTOM))?MPI_BOTTOM:a) */ +#define MPIR_F_PTR(a) (a) + +/* Define the name of the function that we call to initialize the + special symbols */ +#if defined(F77_NAME_LOWER_USCORE) || defined(F77_NAME_LOWER_2USCORE) +/* do nothing */ +#elif defined(F77_NAME_UPPER) +#define mpirinitf_ MPIRINITF +#else +#define mpirinitf_ mpirinitf +#endif +/* Provide a prototype for the mpirinitf function */ +extern void mpirinitf_(void); + +/* + * These are hooks for Fortran characters. + * MPID_FCHAR_T is the type of a Fortran character argument + * MPID_FCHAR_LARG is the "other" argument that some Fortran compilers use + * MPID_FCHAR_STR gives the pointer to the characters + */ +#ifdef MPID_CHARACTERS_ARE_CRAYPVP +typedef MPID_FCHAR_T; +#define MPID_FCHAR_STR(a) (a)->characters +#define MPID_FCHAR_LARG(d) +#else +typedef char *MPID_FCHAR_T; +#define MPID_FCHAR_STR(a) a +#define MPID_FCHAR_LARG(d) ,d +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +/* To avoid constant allocation/deallocation of temporary arrays, define + a small default, predefined array size. */ +#ifndef MPIR_USE_LOCAL_ARRAY +#define MPIR_USE_LOCAL_ARRAY 32 +#endif + +/* Undefine the names that are used in mpi.h for the predefined keyval + copy and delete functions. This is necessary in case the Fortran + compiler uses uppercase names, because in that case there would be + a conflict in the names */ +#ifdef MPI_DUP_FN +#undef MPI_DUP_FN +#undef MPI_NULL_COPY_FN +#undef MPI_NULL_DELETE_FN +#undef MPI_COMM_NULL_COPY_FN +#undef MPI_COMM_NULL_DELETE_FN +#undef MPI_COMM_DUP_FN +#undef MPI_TYPE_NULL_COPY_FN +#undef MPI_TYPE_NULL_DELETE_FN +#undef MPI_TYPE_DUP_FN +#undef MPI_WIN_NULL_COPY_FN +#undef MPI_WIN_NULL_DELETE_FN +#undef MPI_WIN_DUP_FN + +/* Ditto the null datarep conversion */ +#undef MPI_CONVERSION_FN_NULL +#endif /* MPI_DUP_FN */ + +/* A special case to help out when ROMIO is disabled */ +#ifndef HAVE_ROMIO +#ifndef MPI_File_f2c +#define MPI_File_f2c(a) ((MPI_File)(MPI_Aint)(a)) +#endif +#endif /* HAVE_ROMIO */ + +/* The F90 attr copy/delete function prototype and calling convention */ +typedef void (FORT_CALL F90_CopyFunction) (MPI_Fint *, MPI_Fint *, MPI_Aint *, MPI_Aint *, + MPI_Aint *, MPI_Fint *, MPI_Fint *); +typedef void (FORT_CALL F90_DeleteFunction) (MPI_Fint *, MPI_Fint *, MPI_Aint *, MPI_Aint *, + MPI_Fint *); + +void MPII_Keyval_set_f90_proxy(int keyval); + +extern FORT_DLL_SPEC void FORT_CALL mpi_alloc_mem_cptr_(MPI_Aint * size, MPI_Fint * info, + void **baseptr, MPI_Fint * ierr); + +#endif /* MPI_FORTIMPL_H_INCLUDED */ diff --git a/src/binding/abi_fortran/mpif_h/setbot.c.in b/src/binding/abi_fortran/mpif_h/setbot.c.in new file mode 100644 index 00000000000..e3803dd4594 --- /dev/null +++ b/src/binding/abi_fortran/mpif_h/setbot.c.in @@ -0,0 +1,207 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +#include "mpi_fortimpl.h" + + +#ifdef F77_NAME_UPPER +#define mpirinitc_ MPIRINITC +#elif defined(F77_NAME_LOWER_2USCORE) || defined(F77_NAME_LOWER_USCORE) +/* leave name alone */ +#else +#define mpirinitc_ mpirinitc +#endif +/* These functions are called from Fortran so only need prototypes in + this file. Note that the second-to-last argument is a character array, so + we need to include the elements of the Fortran character "dope vector". +*/ +FORT_DLL_SPEC void FORT_CALL mpirinitc_(void *si, void *ssi, + void *bt, void *ip, void *c_ba, + void *uw, void *ecsi, + void *an FORT_MIXED_LEN(d1), + void *asn FORT_MIXED_LEN(d1), + void *we FORT_END_LEN(d1) FORT_END_LEN(d2)); + +/* + # MPI-2, section 4.12.5, on the declaration of MPI_F_STATUS_IGNORE + # MPI_F_STATUSES_IGNORE as global variables in mpi.h (!) +*/ +int MPIR_F_NeedInit = 1; +void *MPIR_F_MPI_BOTTOM = 0; +void *MPIR_F_MPI_IN_PLACE = 0; +void *MPIR_F_MPI_BUFFER_AUTOMATIC = 0; +void *MPIR_F_MPI_UNWEIGHTED = 0; +/* MPI_F_STATUS_IGNORE etc must be declared within mpi.h (MPI-2 standard + requires this) */ +/* +void *MPI_F_STATUS_IGNORE = 0; +void *MPI_F_STATUSES_IGNORE = 0; +*/ +MPI_Fint *MPI_F_ERRCODES_IGNORE = 0; +void *MPI_F_ARGV_NULL = 0; +void *MPI_F_ARGVS_NULL = 0; +void *MPIR_F_MPI_WEIGHTS_EMPTY = 0; + +FORT_DLL_SPEC void FORT_CALL mpirinitc_(void *si, void *ssi, + void *bt, void *ip, void *c_ba, + void *uw, void *ecsi, + void *an FORT_MIXED_LEN(d1), + void *asn FORT_MIXED_LEN(d1), + void *we FORT_END_LEN(d1) FORT_END_LEN(d2)) +{ + MPI_F_STATUS_IGNORE = (MPI_Fint *) si; + MPI_F_STATUSES_IGNORE = (MPI_Fint *) ssi; + MPIR_F_MPI_BOTTOM = bt; + MPIR_F_MPI_IN_PLACE = ip; + MPIR_F_MPI_BUFFER_AUTOMATIC = c_ba; + MPIR_F_MPI_UNWEIGHTED = uw; + MPI_F_ERRCODES_IGNORE = (MPI_Fint *) ecsi; + MPI_F_ARGV_NULL = an; + MPI_F_ARGVS_NULL = asn; + MPIR_F_MPI_WEIGHTS_EMPTY = we; +} + +/* + Enable all known common block symbols mangling to be alias to each other, + i.e. [_C]mpifcmb*[_]to one symbol, mpifcmb*r. + Each common block is defined for one MPI Fortran special constant. + This is done to avoid alignment problem. +*/ + +#if defined(HAVE_C_MULTI_ATTR_ALIAS) + +struct mpif_cmblk1_t_ { + MPI_Fint MPIF_STATUS_IGNORE[MPI_F_STATUS_SIZE]; +}; +typedef struct mpif_cmblk1_t_ mpif_cmblk1_t; +/* *INDENT-OFF* */ +/* The initializer is necessary for the alias to work -- cannot alias to a common symbol. + * The ugly double braces are necessary to silence warnings (due to the first element in + * the struct is of a compound type). + */ +mpif_cmblk1_t mpifcmb1r @CMB_STATUS_ALIGNMENT@ = {{0}}; +/* *INDENT-ON* */ +extern mpif_cmblk1_t _CMPIFCMB1 __attribute__ ((alias("mpifcmb1r"))); +extern mpif_cmblk1_t MPIFCMB1 __attribute__ ((alias("mpifcmb1r"))); +extern mpif_cmblk1_t MPIFCMB1_ __attribute__ ((alias("mpifcmb1r"))); +extern mpif_cmblk1_t _Cmpifcmb1 __attribute__ ((alias("mpifcmb1r"))); +extern mpif_cmblk1_t mpifcmb1 __attribute__ ((alias("mpifcmb1r"))); +extern mpif_cmblk1_t mpifcmb1_ __attribute__ ((alias("mpifcmb1r"))); + +struct mpif_cmblk2_t_ { + MPI_Fint MPIF_STATUSES_IGNORE[1][MPI_F_STATUS_SIZE]; +}; +typedef struct mpif_cmblk2_t_ mpif_cmblk2_t; +/* *INDENT-OFF* */ +mpif_cmblk2_t mpifcmb2r @CMB_STATUS_ALIGNMENT@ = {{{0}}}; +/* *INDENT-ON* */ +extern mpif_cmblk2_t _CMPIFCMB2 __attribute__ ((alias("mpifcmb2r"))); +extern mpif_cmblk2_t MPIFCMB2 __attribute__ ((alias("mpifcmb2r"))); +extern mpif_cmblk2_t MPIFCMB2_ __attribute__ ((alias("mpifcmb2r"))); +extern mpif_cmblk2_t _Cmpifcmb2 __attribute__ ((alias("mpifcmb2r"))); +extern mpif_cmblk2_t mpifcmb2 __attribute__ ((alias("mpifcmb2r"))); +extern mpif_cmblk2_t mpifcmb2_ __attribute__ ((alias("mpifcmb2r"))); + +struct mpif_cmblk3_t_ { + MPI_Fint MPIF_BOTTOM; +}; +typedef struct mpif_cmblk3_t_ mpif_cmblk3_t; +/* *INDENT-OFF* */ +mpif_cmblk3_t mpifcmb3r @CMB_1INT_ALIGNMENT@ = {0}; +/* *INDENT-ON* */ +extern mpif_cmblk3_t _CMPIFCMB3 __attribute__ ((alias("mpifcmb3r"))); +extern mpif_cmblk3_t MPIFCMB3 __attribute__ ((alias("mpifcmb3r"))); +extern mpif_cmblk3_t MPIFCMB3_ __attribute__ ((alias("mpifcmb3r"))); +extern mpif_cmblk3_t _Cmpifcmb3 __attribute__ ((alias("mpifcmb3r"))); +extern mpif_cmblk3_t mpifcmb3 __attribute__ ((alias("mpifcmb3r"))); +extern mpif_cmblk3_t mpifcmb3_ __attribute__ ((alias("mpifcmb3r"))); + +struct mpif_cmblk4_t_ { + MPI_Fint MPIF_IN_PLACE; +}; +typedef struct mpif_cmblk4_t_ mpif_cmblk4_t; +/* *INDENT-OFF* */ +mpif_cmblk4_t mpifcmb4r @CMB_1INT_ALIGNMENT@ = {0}; +/* *INDENT-ON* */ +extern mpif_cmblk4_t _CMPIFCMB4 __attribute__ ((alias("mpifcmb4r"))); +extern mpif_cmblk4_t MPIFCMB4 __attribute__ ((alias("mpifcmb4r"))); +extern mpif_cmblk4_t MPIFCMB4_ __attribute__ ((alias("mpifcmb4r"))); +extern mpif_cmblk4_t _Cmpifcmb4 __attribute__ ((alias("mpifcmb4r"))); +extern mpif_cmblk4_t mpifcmb4 __attribute__ ((alias("mpifcmb4r"))); +extern mpif_cmblk4_t mpifcmb4_ __attribute__ ((alias("mpifcmb4r"))); + +struct mpif_cmblk5_t_ { + MPI_Fint MPIF_UNWEIGHTED; +}; +typedef struct mpif_cmblk5_t_ mpif_cmblk5_t; +/* *INDENT-OFF* */ +FORT_DLL_SPEC mpif_cmblk5_t mpifcmb5r @CMB_1INT_ALIGNMENT@ = {0}; +/* *INDENT-ON* */ +extern FORT_DLL_SPEC mpif_cmblk5_t _CMPIFCMB5 __attribute__ ((alias("mpifcmb5r"))); +extern FORT_DLL_SPEC mpif_cmblk5_t MPIFCMB5 __attribute__ ((alias("mpifcmb5r"))); +extern FORT_DLL_SPEC mpif_cmblk5_t MPIFCMB5_ __attribute__ ((alias("mpifcmb5r"))); +extern FORT_DLL_SPEC mpif_cmblk5_t _Cmpifcmb5 __attribute__ ((alias("mpifcmb5r"))); +extern FORT_DLL_SPEC mpif_cmblk5_t mpifcmb5 __attribute__ ((alias("mpifcmb5r"))); +extern FORT_DLL_SPEC mpif_cmblk5_t mpifcmb5_ __attribute__ ((alias("mpifcmb5r"))); + +struct mpif_cmblk6_t_ { + MPI_Fint MPIF_ERRCODES_IGNORE[1]; +}; +typedef struct mpif_cmblk6_t_ mpif_cmblk6_t; +/* *INDENT-OFF* */ +mpif_cmblk6_t mpifcmb6r @CMB_1INT_ALIGNMENT@ = {{0}}; +/* *INDENT-ON* */ +extern mpif_cmblk6_t _CMPIFCMB6 __attribute__ ((alias("mpifcmb6r"))); +extern mpif_cmblk6_t MPIFCMB6 __attribute__ ((alias("mpifcmb6r"))); +extern mpif_cmblk6_t MPIFCMB6_ __attribute__ ((alias("mpifcmb6r"))); +extern mpif_cmblk6_t _Cmpifcmb6 __attribute__ ((alias("mpifcmb6r"))); +extern mpif_cmblk6_t mpifcmb6 __attribute__ ((alias("mpifcmb6r"))); +extern mpif_cmblk6_t mpifcmb6_ __attribute__ ((alias("mpifcmb6r"))); + +struct mpif_cmblk7_t_ { + char MPIF_ARGVS_NULL[1][1]; + char pads[3]; +}; +typedef struct mpif_cmblk7_t_ mpif_cmblk7_t; +/* *INDENT-OFF* */ +mpif_cmblk7_t mpifcmb7r @CMB_1INT_ALIGNMENT@ = {{{0}},{0}}; +/* *INDENT-ON* */ +extern mpif_cmblk7_t _CMPIFCMB7 __attribute__ ((alias("mpifcmb7r"))); +extern mpif_cmblk7_t MPIFCMB7 __attribute__ ((alias("mpifcmb7r"))); +extern mpif_cmblk7_t MPIFCMB7_ __attribute__ ((alias("mpifcmb7r"))); +extern mpif_cmblk7_t _Cmpifcmb7 __attribute__ ((alias("mpifcmb7r"))); +extern mpif_cmblk7_t mpifcmb7 __attribute__ ((alias("mpifcmb7r"))); +extern mpif_cmblk7_t mpifcmb7_ __attribute__ ((alias("mpifcmb7r"))); + +struct mpif_cmblk8_t_ { + char MPIF_ARGV_NULL[1]; + char pads[3]; +}; +typedef struct mpif_cmblk8_t_ mpif_cmblk8_t; +/* *INDENT-OFF* */ +mpif_cmblk8_t mpifcmb8r @CMB_1INT_ALIGNMENT@ = {{0},{0}}; +/* *INDENT-ON* */ +extern mpif_cmblk8_t _CMPIFCMB8 __attribute__ ((alias("mpifcmb8r"))); +extern mpif_cmblk8_t MPIFCMB8 __attribute__ ((alias("mpifcmb8r"))); +extern mpif_cmblk8_t MPIFCMB8_ __attribute__ ((alias("mpifcmb8r"))); +extern mpif_cmblk8_t _Cmpifcmb8 __attribute__ ((alias("mpifcmb8r"))); +extern mpif_cmblk8_t mpifcmb8 __attribute__ ((alias("mpifcmb8r"))); +extern mpif_cmblk8_t mpifcmb8_ __attribute__ ((alias("mpifcmb8r"))); + +struct mpif_cmblk9_t_ { + MPI_Fint MPIF_WEIGHTS_EMPTY; +}; +typedef struct mpif_cmblk9_t_ mpif_cmblk9_t; +/* *INDENT-OFF* */ +FORT_DLL_SPEC mpif_cmblk9_t mpifcmb9r @CMB_1INT_ALIGNMENT@ = {0}; +/* *INDENT-ON* */ +extern FORT_DLL_SPEC mpif_cmblk9_t _CMPIFCMB9 __attribute__ ((alias("mpifcmb9r"))); +extern FORT_DLL_SPEC mpif_cmblk9_t MPIFCMB9 __attribute__ ((alias("mpifcmb9r"))); +extern FORT_DLL_SPEC mpif_cmblk9_t MPIFCMB9_ __attribute__ ((alias("mpifcmb9r"))); +extern FORT_DLL_SPEC mpif_cmblk9_t _Cmpifcmb9 __attribute__ ((alias("mpifcmb9r"))); +extern FORT_DLL_SPEC mpif_cmblk9_t mpifcmb9 __attribute__ ((alias("mpifcmb9r"))); +extern FORT_DLL_SPEC mpif_cmblk9_t mpifcmb9_ __attribute__ ((alias("mpifcmb9r"))); + +#endif diff --git a/src/binding/abi_fortran/mpif_h/setbotf.f.in b/src/binding/abi_fortran/mpif_h/setbotf.f.in new file mode 100644 index 00000000000..b99249e8a26 --- /dev/null +++ b/src/binding/abi_fortran/mpif_h/setbotf.f.in @@ -0,0 +1,29 @@ +! +! Copyright (C) by Argonne National Laboratory +! See COPYRIGHT in top-level directory +! + subroutine mpirinitf( ) + integer mpi_status_size + parameter (mpi_status_size=@MPI_STATUS_SIZE@) +! STATUS_IGNORE, STATUSES_IGNORE + integer si(mpi_status_size), ssi(mpi_status_size,1) +! BOTTOM, IN_PLACE, UNWEIGHTED, WEIGHTED, ERRCODES_IGNORE + integer bt, ip, c_ba(1), uw(1), we(1), ecsi(1) +! ARGVS_NULL, ARGV_NULL + character*1 asn(1,1), an(1) + common /MPIFCMB5/ uw + common /MPIFCMB9/ we + common /MPIFCMBa/ c_ba + common /MPIPRIV1/ bt, ip, si + common /MPIPRIV2/ ssi, ecsi + common /MPIPRIVC/ asn, an + save /MPIFCMB5/ + save /MPIFCMB9/ + save /MPIFCMBa/ + save /MPIPRIV1/, /MPIPRIV2/ + save /MPIPRIVC/ +! MPI_ARGVS_NULL +! (Fortran requires character data in a separate common block) + call mpirinitc(si, ssi, bt, ip, c_ba, uw, ecsi, an, asn, we) + return + end diff --git a/src/binding/abi_fortran/use_mpi/Makefile.mk b/src/binding/abi_fortran/use_mpi/Makefile.mk new file mode 100644 index 00000000000..d0284960f56 --- /dev/null +++ b/src/binding/abi_fortran/use_mpi/Makefile.mk @@ -0,0 +1,261 @@ +## +## Copyright (C) by Argonne National Laboratory +## See COPYRIGHT in top-level directory +## + +MOD = @FCMODEXT@ +MPIMOD = @MPIMODNAME@ +MPICONSTMOD = @MPICONSTMODNAME@ +MPISIZEOFMOD = @MPISIZEOFMODNAME@ +MPIBASEMOD = @MPIBASEMODNAME@ +PMPIBASEMOD = @PMPIBASEMODNAME@ +FC_COMPILE_MODS = $(LTFCCOMPILE) + +# variables for custom "silent-rules" for F90 modules +mod_verbose = $(mod_verbose_$(V)) +mod_verbose_ = $(mod_verbose_$(AM_DEFAULT_VERBOSITY)) +mod_verbose_0 = @echo " MOD " $@; + +if BUILD_FC_BINDING + +# We need to tell some compilers (e.g., Solaris f90) to look for modules in the +# current directory when the source file is not in the working directory (i.e., +# in a VPATH build) +AM_FCFLAGS += @FCINCFLAG@src/binding/fortran/use_mpi + +AM_CPPFLAGS += -Isrc/binding/fortran/use_mpi +noinst_HEADERS += \ + src/binding/fortran/use_mpi/mpifnoext.h + +# cause any .$(MOD) files to be output in the f90 bindings directory instead of +# the current directory +FC_COMPILE_MODS += $(FCMODOUTFLAG)src/binding/fortran/use_mpi + +mpifort_convenience_libs += lib/libf90_mpi.la +noinst_LTLIBRARIES += lib/libf90_mpi.la + +lib_libf90_mpi_la_SOURCES = \ + src/binding/fortran/use_mpi/mpi.f90 \ + src/binding/fortran/use_mpi/mpi_constants.f90 \ + src/binding/fortran/use_mpi/mpi_sizeofs.f90 \ + src/binding/fortran/use_mpi/mpi_base.f90 \ + src/binding/fortran/use_mpi/pmpi_base.f90 + +# FIXME: We may want to edit the mpif.h to convert Fortran77-specific +# items (such as an integer*8 used for file offsets) into the +# corresponding Fortran 90 KIND type, to accommodate compilers that +# reject non-standard features such as integer*8 (such as the Intel +# Fortran compiler with -std95). +# We need the MPI constants in a separate module for some of the +# interface definitions (the ones that need MPI_ADDRESS_KIND or +# MPI_OFFSET_KIND) +src/binding/fortran/use_mpi/mpi.$(MOD)-stamp: src/binding/fortran/use_mpi/$(MPICONSTMOD).$(MOD) src/binding/fortran/use_mpi/$(MPISIZEOFMOD).$(MOD) src/binding/fortran/use_mpi/$(MPIBASEMOD).$(MOD) src/binding/fortran/use_mpi/$(PMPIBASEMOD).$(MOD) $(srcdir)/src/binding/fortran/use_mpi/mpi.f90 src/binding/fortran/use_mpi/mpifnoext.h + @rm -f src/binding/fortran/use_mpi/mpi-tmp + @touch src/binding/fortran/use_mpi/mpi-tmp + @( cd src/binding/fortran/use_mpi && \ + if [ "$(FCEXT)" != "f90" ] || [ ! -f mpi.$(FCEXT) ] ; then \ + rm -f mpi.$(FCEXT) ; \ + $(LN_S) $(abs_top_srcdir)/src/binding/fortran/use_mpi/mpi.f90 mpi.$(FCEXT) ; \ + fi ) + $(mod_verbose)$(FC_COMPILE_MODS) -c src/binding/fortran/use_mpi/mpi.$(FCEXT) -o src/binding/fortran/use_mpi/mpi.lo + @( cd src/binding/fortran/use_mpi && \ + if [ "$(FCEXT)" != "f90" ] || [ ! -f mpi.$(FCEXT) ] ; then \ + rm -f mpi.$(FCEXT) ; \ + fi ) + @mv src/binding/fortran/use_mpi/mpi-tmp src/binding/fortran/use_mpi/mpi.$(MOD)-stamp + +src/binding/fortran/use_mpi/mpi.lo src/binding/fortran/use_mpi/$(MPIMOD).$(MOD): src/binding/fortran/use_mpi/mpi.$(MOD)-stamp +## Recover from the removal of $@ + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi/mpi-lock src/binding/fortran/use_mpi/mpi.$(MOD)-stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi/mpi-lock 2>/dev/null; then \ +## This code is being executed by the first process. + rm -f src/binding/fortran/use_mpi/mpi.$(MOD)-stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi/mpi.$(MOD)-stamp; \ + rmdir src/binding/fortran/use_mpi/mpi-lock; \ + else \ +## This code is being executed by the follower processes. +## Wait until the first process is done. + while test -d src/binding/fortran/use_mpi/mpi-lock; do sleep 1; done; \ +## Succeed if and only if the first process succeeded. + test -f src/binding/fortran/use_mpi/mpi.$(MOD)-stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi/mpi.$(MOD)-stamp src/binding/fortran/use_mpi/$(MPIMOD).$(MOD) src/binding/fortran/use_mpi/mpi.lo src/binding/fortran/use_mpi/mpi-tmp + + +src/binding/fortran/use_mpi/mpi_constants.$(MOD)-stamp: src/binding/fortran/use_mpi/mpi_constants.f90 src/binding/fortran/use_mpi/mpifnoext.h + @rm -f src/binding/fortran/use_mpi/mpi_constants-tmp + @touch src/binding/fortran/use_mpi/mpi_constants-tmp + @( cd src/binding/fortran/use_mpi && \ + if [ "$(FCEXT)" != "f90" ] || [ ! -f mpi_constants.$(FCEXT) ] ; then \ + rm -f mpi_constants.$(FCEXT) ; \ + $(LN_S) $(abs_top_srcdir)/src/binding/fortran/use_mpi/mpi_constants.f90 mpi_constants.$(FCEXT) ; \ + fi ) + $(mod_verbose)$(FC_COMPILE_MODS) -c src/binding/fortran/use_mpi/mpi_constants.$(FCEXT) -o src/binding/fortran/use_mpi/mpi_constants.lo + @( cd src/binding/fortran/use_mpi && \ + if [ "$(FCEXT)" != "f90" ] || [ ! -f mpi_constants.$(FCEXT) ] ; then \ + rm -f mpi_constants.$(FCEXT) ; \ + fi ) + @mv src/binding/fortran/use_mpi/mpi_constants-tmp src/binding/fortran/use_mpi/mpi_constants.$(MOD)-stamp + +src/binding/fortran/use_mpi/mpi_constants.lo src/binding/fortran/use_mpi/$(MPICONSTMOD).$(MOD): src/binding/fortran/use_mpi/mpi_constants.$(MOD)-stamp +## Recover from the removal of $@ + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi/mpi_constants-lock src/binding/fortran/use_mpi/mpi_constants.$(MOD)-stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi/mpi_constants-lock 2>/dev/null; then \ +## This code is being executed by the first process. + rm -f src/binding/fortran/use_mpi/mpi_constants.$(MOD)-stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi/mpi_constants.$(MOD)-stamp; \ + rmdir src/binding/fortran/use_mpi/mpi_constants-lock; \ + else \ +## This code is being executed by the follower processes. +## Wait until the first process is done. + while test -d src/binding/fortran/use_mpi/mpi_constants-lock; do sleep 1; done; \ +## Succeed if and only if the first process succeeded. + test -f src/binding/fortran/use_mpi/mpi_constants.$(MOD)-stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi/mpi_constants.$(MOD)-stamp src/binding/fortran/use_mpi/$(MPICONSTMOD).$(MOD) src/binding/fortran/use_mpi/mpi_constants.lo src/binding/fortran/use_mpi/mpi_constants-tmp + + +src/binding/fortran/use_mpi/mpi_sizeofs.$(MOD)-stamp: src/binding/fortran/use_mpi/mpi_sizeofs.f90 src/binding/fortran/use_mpi/mpifnoext.h + @rm -f src/binding/fortran/use_mpi/mpi_sizeofs-tmp + @touch src/binding/fortran/use_mpi/mpi_sizeofs-tmp + @( cd src/binding/fortran/use_mpi && \ + if [ "$(FCEXT)" != "f90" ] ; then \ + rm -f mpi_sizeofs.$(FCEXT) ; \ + $(LN_S) mpi_sizeofs.f90 mpi_sizeofs.$(FCEXT) ; \ + fi ) + $(mod_verbose)$(FC_COMPILE_MODS) -c src/binding/fortran/use_mpi/mpi_sizeofs.$(FCEXT) -o src/binding/fortran/use_mpi/mpi_sizeofs.lo + @( cd src/binding/fortran/use_mpi && \ + if [ "$(FCEXT)" != "f90" ] ; then \ + rm -f mpi_sizeofs.$(FCEXT) ; \ + fi ) + @mv src/binding/fortran/use_mpi/mpi_sizeofs-tmp src/binding/fortran/use_mpi/mpi_sizeofs.$(MOD)-stamp + +src/binding/fortran/use_mpi/mpi_sizeofs.lo src/binding/fortran/use_mpi/$(MPISIZEOFMOD).$(MOD): src/binding/fortran/use_mpi/mpi_sizeofs.$(MOD)-stamp +## Recover from the removal of $@ + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi/mpi_sizeofs-lock src/binding/fortran/use_mpi/mpi_sizeofs.$(MOD)-stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi/mpi_sizeofs-lock 2>/dev/null; then \ +## This code is being executed by the first process. + rm -f src/binding/fortran/use_mpi/mpi_sizeofs.$(MOD)-stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi/mpi_sizeofs.$(MOD)-stamp; \ + rmdir src/binding/fortran/use_mpi/mpi_sizeofs-lock; \ + else \ +## This code is being executed by the follower processes. +## Wait until the first process is done. + while test -d src/binding/fortran/use_mpi/mpi_sizeofs-lock; do sleep 1; done; \ +## Succeed if and only if the first process succeeded. + test -f src/binding/fortran/use_mpi/mpi_sizeofs.$(MOD)-stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi/mpi_sizeofs.$(MOD)-stamp src/binding/fortran/use_mpi/$(MPISIZEOFMOD).$(MOD) src/binding/fortran/use_mpi/mpi_sizeofs.lo src/binding/fortran/use_mpi/mpi_sizeofs-tmp + + +src/binding/fortran/use_mpi/mpi_base.$(MOD)-stamp: src/binding/fortran/use_mpi/mpi_base.f90 src/binding/fortran/use_mpi/$(MPICONSTMOD).$(MOD) + @rm -f src/binding/fortran/use_mpi/mpi_base-tmp + @touch src/binding/fortran/use_mpi/mpi_base-tmp + @( cd src/binding/fortran/use_mpi && \ + if [ "$(FCEXT)" != "f90" ] ; then \ + rm -f mpi_base.$(FCEXT) ; \ + $(LN_S) mpi_base.f90 mpi_base.$(FCEXT) ; \ + fi ) + $(mod_verbose)$(FC_COMPILE_MODS) -c src/binding/fortran/use_mpi/mpi_base.$(FCEXT) -o src/binding/fortran/use_mpi/mpi_base.lo + @( cd src/binding/fortran/use_mpi && \ + if [ "$(FCEXT)" != "f90" ] ; then \ + rm -f mpi_base.$(FCEXT) ; \ + fi ) + @mv src/binding/fortran/use_mpi/mpi_base-tmp src/binding/fortran/use_mpi/mpi_base.$(MOD)-stamp + +src/binding/fortran/use_mpi/mpi_base.lo src/binding/fortran/use_mpi/$(MPIBASEMOD).$(MOD): src/binding/fortran/use_mpi/mpi_base.$(MOD)-stamp +## Recover from the removal of $@ + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi/mpi_base-lock src/binding/fortran/use_mpi/mpi_base.$(MOD)-stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi/mpi_base-lock 2>/dev/null; then \ +## This code is being executed by the first process. + rm -f src/binding/fortran/use_mpi/mpi_base.$(MOD)-stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi/mpi_base.$(MOD)-stamp; \ + rmdir src/binding/fortran/use_mpi/mpi_base-lock; \ + else \ +## This code is being executed by the follower processes. +## Wait until the first process is done. + while test -d src/binding/fortran/use_mpi/mpi_base-lock; do sleep 1; done; \ +## Succeed if and only if the first process succeeded. + test -f src/binding/fortran/use_mpi/mpi_base.$(MOD)-stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi/mpi_base.$(MOD)-stamp src/binding/fortran/use_mpi/$(MPIBASEMOD).$(MOD) src/binding/fortran/use_mpi/mpi_base.lo src/binding/fortran/use_mpi/mpi_base-tmp + +src/binding/fortran/use_mpi/pmpi_base.$(MOD)-stamp: src/binding/fortran/use_mpi/pmpi_base.f90 src/binding/fortran/use_mpi/$(MPICONSTMOD).$(MOD) + @rm -f src/binding/fortran/use_mpi/pmpi_base-tmp + @touch src/binding/fortran/use_mpi/pmpi_base-tmp + @( cd src/binding/fortran/use_mpi && \ + if [ "$(FCEXT)" != "f90" ] ; then \ + rm -f pmpi_base.$(FCEXT) ; \ + $(LN_S) pmpi_base.f90 pmpi_base.$(FCEXT) ; \ + fi ) + $(mod_verbose)$(FC_COMPILE_MODS) -c src/binding/fortran/use_mpi/pmpi_base.$(FCEXT) -o src/binding/fortran/use_mpi/pmpi_base.lo + @( cd src/binding/fortran/use_mpi && \ + if [ "$(FCEXT)" != "f90" ] ; then \ + rm -f pmpi_base.$(FCEXT) ; \ + fi ) + @mv src/binding/fortran/use_mpi/pmpi_base-tmp src/binding/fortran/use_mpi/pmpi_base.$(MOD)-stamp + +src/binding/fortran/use_mpi/pmpi_base.lo src/binding/fortran/use_mpi/$(PMPIBASEMOD).$(MOD): src/binding/fortran/use_mpi/pmpi_base.$(MOD)-stamp +## Recover from the removal of $@ + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi/pmpi_base-lock src/binding/fortran/use_mpi/pmpi_base.$(MOD)-stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi/pmpi_base-lock 2>/dev/null; then \ +## This code is being executed by the first process. + rm -f src/binding/fortran/use_mpi/pmpi_base.$(MOD)-stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi/pmpi_base.$(MOD)-stamp; \ + rmdir src/binding/fortran/use_mpi/pmpi_base-lock; \ + else \ +## This code is being executed by the follower processes. +## Wait until the first process is done. + while test -d src/binding/fortran/use_mpi/pmpi_base-lock; do sleep 1; done; \ +## Succeed if and only if the first process succeeded. + test -f src/binding/fortran/use_mpi/pmpi_base.$(MOD)-stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi/pmpi_base.$(MOD)-stamp src/binding/fortran/use_mpi/$(PMPIBASEMOD).$(MOD) src/binding/fortran/use_mpi/pmpi_base.lo src/binding/fortran/use_mpi/pmpi_base-tmp + + +mpi_fc_modules += \ + src/binding/fortran/use_mpi/$(MPIMOD).$(MOD) \ + src/binding/fortran/use_mpi/$(MPISIZEOFMOD).$(MOD) \ + src/binding/fortran/use_mpi/$(MPICONSTMOD).$(MOD) \ + src/binding/fortran/use_mpi/$(MPIBASEMOD).$(MOD) \ + src/binding/fortran/use_mpi/$(PMPIBASEMOD).$(MOD) + +# We need a free-format version of mpif.h with no external commands, +# including declarations such as `REAL*8 MPI_WTIME, PMPI_WTIME`. +# Filtering on `PMPI_` covers those lines. +# NOTE: do not use extended regex to allow posix sed. +src/binding/fortran/use_mpi/mpifnoext.h: src/binding/fortran/mpif_h/mpif.h + rm -f $@ + sed -e 's/^C/\!/g' -e '/EXTERNAL/d' \ + -e '/PMPI_/d' src/binding/fortran/mpif_h/mpif.h > $@ + +CLEANFILES += src/binding/fortran/use_mpi/mpifnoext.h + +MAINTAINERCLEANFILES += $(mpi_sources) fproto.h +CLEANFILES += $(mpi_fc_modules) + +# Documentation sources +# FIXME disabled for now until we sort out how to handle docs correctly in the +# new build system +#doc_sources = +#DOCDESTDIRS = html:www/www1,man:man/man1,latex:doc/refman +#doc_HTML_SOURCES = ${doc_sources} +#doc_MAN_SOURCES = ${doc_sources} +#doc_LATEX_SOURCES = ${doc_sources} + +endif BUILD_FC_BINDING diff --git a/src/binding/abi_fortran/use_mpi/mpi.f90 b/src/binding/abi_fortran/use_mpi/mpi.f90 new file mode 100644 index 00000000000..6b7390bb20f --- /dev/null +++ b/src/binding/abi_fortran/use_mpi/mpi.f90 @@ -0,0 +1,9 @@ +! Copyright (C) by Argonne National Laboratory +! See COPYRIGHT in top-level directory + +MODULE MPI + USE MPI_CONSTANTS + USE MPI_SIZEOFS + USE MPI_BASE + USE PMPI_BASE +END MODULE MPI diff --git a/src/binding/abi_fortran/use_mpi_f08/Makefile.mk b/src/binding/abi_fortran/use_mpi_f08/Makefile.mk new file mode 100644 index 00000000000..8ff957ef7e8 --- /dev/null +++ b/src/binding/abi_fortran/use_mpi_f08/Makefile.mk @@ -0,0 +1,333 @@ +# +# Copyright (C) by Argonne National Laboratory +# See COPYRIGHT in top-level directory +# + +if BUILD_F08_BINDING + +AM_FCFLAGS += @FCINCFLAG@src/binding/fortran/use_mpi_f08 + +mpifort_convenience_libs += lib/libf08_mpi.la +noinst_LTLIBRARIES += lib/libf08_mpi.la + +lib_libf08_mpi_la_SOURCES = \ + src/binding/fortran/use_mpi_f08/pmpi_f08.f90 \ + src/binding/fortran/use_mpi_f08/mpi_f08.f90 \ + src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.f90 \ + src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.f90 \ + src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.f90 \ + src/binding/fortran/use_mpi_f08/mpi_f08_types.f90 \ + src/binding/fortran/use_mpi_f08/mpi_c_interface.f90 \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.f90 \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.f90 \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.f90 \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_types.f90 \ + src/binding/fortran/use_mpi_f08/wrappers_f/f08ts.f90 \ + src/binding/fortran/use_mpi_f08/wrappers_f/pf08ts.f90 \ + src/binding/fortran/use_mpi_f08/wrappers_c/f08_cdesc.c \ + src/binding/fortran/use_mpi_f08/wrappers_c/cdesc.c \ + src/binding/fortran/use_mpi_f08/wrappers_c/comm_spawn_c.c \ + src/binding/fortran/use_mpi_f08/wrappers_c/comm_spawn_multiple_c.c \ + src/binding/fortran/use_mpi_f08/wrappers_c/utils.c + +lib_libf08_mpi_la_CPPFLAGS = $(AM_CPPFLAGS) -I${main_top_srcdir}/src/binding/fortran/use_mpi_f08/wrappers_c -Isrc/binding/fortran/use_mpi_f08/wrappers_c + +noinst_HEADERS += src/binding/fortran/use_mpi_f08/wrappers_c/cdesc.h + +mpi_fc_modules += \ + src/binding/fortran/use_mpi_f08/$(PMPI_F08_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_F08_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_F08_CALLBACKS_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_F08_COMPILE_CONSTANTS_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_F08_LINK_CONSTANTS_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_F08_TYPES_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_CDESC_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_GLUE_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_NOBUF_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_TYPES_NAME).$(MOD) + +f08_module_files = \ + src/binding/fortran/use_mpi_f08/$(MPI_F08_TYPES_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_F08_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_GLUE_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_TYPES_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_F08_COMPILE_CONSTANTS_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_CDESC_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_F08_CALLBACKS_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_NOBUF_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_F08_LINK_CONSTANTS_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(PMPI_F08_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_NAME).$(MOD) + +BUILT_SOURCES += $(f08_module_files) +CLEANFILES += $(f08_module_files) + +F08_COMPILE_MODS = $(LTFCCOMPILE) +F08_COMPILE_MODS += $(FCMODOUTFLAG)src/binding/fortran/use_mpi_f08 + +src/binding/fortran/use_mpi_f08/mpi_f08_types.stamp: src/binding/fortran/use_mpi_f08/mpi_f08_types.f90 src/binding/fortran/use_mpi_f08/mpi_c_interface_types.stamp + @rm -f src/binding/fortran/use_mpi_f08/mpi_f08_types.tmp + @touch src/binding/fortran/use_mpi_f08/mpi_f08_types.tmp + $(mod_verbose)$(F08_COMPILE_MODS) -c `test -f 'src/binding/fortran/use_mpi_f08/mpi_f08_types.f90' || echo '$(srcdir)/'`src/binding/fortran/use_mpi_f08/mpi_f08_types.f90 -o src/binding/fortran/use_mpi_f08/mpi_f08_types.lo + @mv src/binding/fortran/use_mpi_f08/mpi_f08_types.tmp src/binding/fortran/use_mpi_f08/mpi_f08_types.stamp + +src/binding/fortran/use_mpi_f08/$(MPI_F08_TYPES_NAME).$(MOD) src/binding/fortran/use_mpi_f08/mpi_f08_types.lo : src/binding/fortran/use_mpi_f08/mpi_f08_types.stamp + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi_f08/mpi_f08_types-lock src/binding/fortran/use_mpi_f08/mpi_f08_types.stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi_f08/mpi_f08_types-lock 2>/dev/null; then \ + rm -f src/binding/fortran/use_mpi_f08/mpi_f08_types.stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi_f08/mpi_f08_types.stamp; \ + rmdir src/binding/fortran/use_mpi_f08/mpi_f08_types-lock; \ + else \ + while test -d src/binding/fortran/use_mpi_f08/mpi_f08_types-lock; do sleep 1; done; \ + test -f src/binding/fortran/use_mpi_f08/mpi_f08_types.stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi_f08/$(MPI_F08_TYPES_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/mpi_f08_types.lo \ + src/binding/fortran/use_mpi_f08/mpi_f08_types.stamp \ + src/binding/fortran/use_mpi_f08/mpi_f08_types.tmp + +src/binding/fortran/use_mpi_f08/mpi_f08.stamp: src/binding/fortran/use_mpi_f08/mpi_f08.f90 src/binding/fortran/use_mpi_f08/pmpi_f08.stamp + @rm -f src/binding/fortran/use_mpi_f08/mpi_f08.tmp + @touch src/binding/fortran/use_mpi_f08/mpi_f08.tmp + $(mod_verbose)$(F08_COMPILE_MODS) -c `test -f 'src/binding/fortran/use_mpi_f08/mpi_f08.f90' || echo '$(srcdir)/'`src/binding/fortran/use_mpi_f08/mpi_f08.f90 -o src/binding/fortran/use_mpi_f08/mpi_f08.lo + @mv src/binding/fortran/use_mpi_f08/mpi_f08.tmp src/binding/fortran/use_mpi_f08/mpi_f08.stamp + +src/binding/fortran/use_mpi_f08/$(MPI_F08_NAME).$(MOD) src/binding/fortran/use_mpi_f08/mpi_f08.lo : src/binding/fortran/use_mpi_f08/mpi_f08.stamp + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi_f08/mpi_f08-lock src/binding/fortran/use_mpi_f08/mpi_f08.stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi_f08/mpi_f08-lock 2>/dev/null; then \ + rm -f src/binding/fortran/use_mpi_f08/mpi_f08.stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi_f08/mpi_f08.stamp; \ + rmdir src/binding/fortran/use_mpi_f08/mpi_f08-lock; \ + else \ + while test -d src/binding/fortran/use_mpi_f08/mpi_f08-lock; do sleep 1; done; \ + test -f src/binding/fortran/use_mpi_f08/mpi_f08.stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi_f08/$(MPI_F08_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/mpi_f08.lo \ + src/binding/fortran/use_mpi_f08/mpi_f08.stamp \ + src/binding/fortran/use_mpi_f08/mpi_f08.tmp + +src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.stamp: src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.f90 src/binding/fortran/use_mpi_f08/mpi_f08.stamp + @rm -f src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.tmp + @touch src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.tmp + $(mod_verbose)$(F08_COMPILE_MODS) -c `test -f 'src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.f90' || echo '$(srcdir)/'`src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.f90 -o src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.lo + @mv src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.tmp src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.stamp + +src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_GLUE_NAME).$(MOD) src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.lo : src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.stamp + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi_f08/mpi_c_interface_glue-lock src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi_f08/mpi_c_interface_glue-lock 2>/dev/null; then \ + rm -f src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.stamp; \ + rmdir src/binding/fortran/use_mpi_f08/mpi_c_interface_glue-lock; \ + else \ + while test -d src/binding/fortran/use_mpi_f08/mpi_c_interface_glue-lock; do sleep 1; done; \ + test -f src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_GLUE_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.lo \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.stamp \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.tmp + +src/binding/fortran/use_mpi_f08/mpi_c_interface_types.stamp: src/binding/fortran/use_mpi_f08/mpi_c_interface_types.f90 + @rm -f src/binding/fortran/use_mpi_f08/mpi_c_interface_types.tmp + @touch src/binding/fortran/use_mpi_f08/mpi_c_interface_types.tmp + $(mod_verbose)$(F08_COMPILE_MODS) -c `test -f 'src/binding/fortran/use_mpi_f08/mpi_c_interface_types.f90' || echo '$(srcdir)/'`src/binding/fortran/use_mpi_f08/mpi_c_interface_types.f90 -o src/binding/fortran/use_mpi_f08/mpi_c_interface_types.lo + @mv src/binding/fortran/use_mpi_f08/mpi_c_interface_types.tmp src/binding/fortran/use_mpi_f08/mpi_c_interface_types.stamp + +src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_TYPES_NAME).$(MOD) src/binding/fortran/use_mpi_f08/mpi_c_interface_types.lo : src/binding/fortran/use_mpi_f08/mpi_c_interface_types.stamp + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi_f08/mpi_c_interface_types-lock src/binding/fortran/use_mpi_f08/mpi_c_interface_types.stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi_f08/mpi_c_interface_types-lock 2>/dev/null; then \ + rm -f src/binding/fortran/use_mpi_f08/mpi_c_interface_types.stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi_f08/mpi_c_interface_types.stamp; \ + rmdir src/binding/fortran/use_mpi_f08/mpi_c_interface_types-lock; \ + else \ + while test -d src/binding/fortran/use_mpi_f08/mpi_c_interface_types-lock; do sleep 1; done; \ + test -f src/binding/fortran/use_mpi_f08/mpi_c_interface_types.stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_TYPES_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_types.lo \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_types.stamp \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_types.tmp + +src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.stamp: src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.f90 src/binding/fortran/use_mpi_f08/mpi_f08_types.stamp + @rm -f src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.tmp + @touch src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.tmp + $(mod_verbose)$(F08_COMPILE_MODS) -c `test -f 'src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.f90' || echo '$(srcdir)/'`src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.f90 -o src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.lo + @mv src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.tmp src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.stamp + +src/binding/fortran/use_mpi_f08/$(MPI_F08_COMPILE_CONSTANTS_NAME).$(MOD) src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.lo : src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.stamp + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants-lock src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants-lock 2>/dev/null; then \ + rm -f src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.stamp; \ + rmdir src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants-lock; \ + else \ + while test -d src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants-lock; do sleep 1; done; \ + test -f src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi_f08/$(MPI_F08_COMPILE_CONSTANTS_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.lo \ + src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.stamp \ + src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.tmp + +src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.stamp: src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.f90 src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.stamp + @rm -f src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.tmp + @touch src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.tmp + $(mod_verbose)$(F08_COMPILE_MODS) -c `test -f 'src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.f90' || echo '$(srcdir)/'`src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.f90 -o src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.lo + @mv src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.tmp src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.stamp + +src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_CDESC_NAME).$(MOD) src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.lo : src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.stamp + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc-lock src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc-lock 2>/dev/null; then \ + rm -f src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.stamp; \ + rmdir src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc-lock; \ + else \ + while test -d src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc-lock; do sleep 1; done; \ + test -f src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_CDESC_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.lo \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.stamp \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.tmp + +src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.stamp: src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.f90 src/binding/fortran/use_mpi_f08/mpi_f08_compile_constants.stamp + @rm -f src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.tmp + @touch src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.tmp + $(mod_verbose)$(F08_COMPILE_MODS) -c `test -f 'src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.f90' || echo '$(srcdir)/'`src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.f90 -o src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.lo + @mv src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.tmp src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.stamp + +src/binding/fortran/use_mpi_f08/$(MPI_F08_CALLBACKS_NAME).$(MOD) src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.lo : src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.stamp + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi_f08/mpi_f08_callbacks-lock src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi_f08/mpi_f08_callbacks-lock 2>/dev/null; then \ + rm -f src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.stamp; \ + rmdir src/binding/fortran/use_mpi_f08/mpi_f08_callbacks-lock; \ + else \ + while test -d src/binding/fortran/use_mpi_f08/mpi_f08_callbacks-lock; do sleep 1; done; \ + test -f src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi_f08/$(MPI_F08_CALLBACKS_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.lo \ + src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.stamp \ + src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.tmp + +src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.stamp: src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.f90 src/binding/fortran/use_mpi_f08/mpi_c_interface_glue.stamp + @rm -f src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.tmp + @touch src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.tmp + $(mod_verbose)$(F08_COMPILE_MODS) -c `test -f 'src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.f90' || echo '$(srcdir)/'`src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.f90 -o src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.lo + @mv src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.tmp src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.stamp + +src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_NOBUF_NAME).$(MOD) src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.lo : src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.stamp + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf-lock src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf-lock 2>/dev/null; then \ + rm -f src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.stamp; \ + rmdir src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf-lock; \ + else \ + while test -d src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf-lock; do sleep 1; done; \ + test -f src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_NOBUF_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.lo \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.stamp \ + src/binding/fortran/use_mpi_f08/mpi_c_interface_nobuf.tmp + +src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.stamp: src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.f90 src/binding/fortran/use_mpi_f08/mpi_f08_callbacks.stamp + @rm -f src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.tmp + @touch src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.tmp + $(mod_verbose)$(F08_COMPILE_MODS) -c `test -f 'src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.f90' || echo '$(srcdir)/'`src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.f90 -o src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.lo + @mv src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.tmp src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.stamp + +src/binding/fortran/use_mpi_f08/$(MPI_F08_LINK_CONSTANTS_NAME).$(MOD) src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.lo : src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.stamp + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi_f08/mpi_f08_link_constants-lock src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi_f08/mpi_f08_link_constants-lock 2>/dev/null; then \ + rm -f src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.stamp; \ + rmdir src/binding/fortran/use_mpi_f08/mpi_f08_link_constants-lock; \ + else \ + while test -d src/binding/fortran/use_mpi_f08/mpi_f08_link_constants-lock; do sleep 1; done; \ + test -f src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi_f08/$(MPI_F08_LINK_CONSTANTS_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.lo \ + src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.stamp \ + src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.tmp + +src/binding/fortran/use_mpi_f08/pmpi_f08.stamp: src/binding/fortran/use_mpi_f08/pmpi_f08.f90 src/binding/fortran/use_mpi_f08/mpi_f08_link_constants.stamp + @rm -f src/binding/fortran/use_mpi_f08/pmpi_f08.tmp + @touch src/binding/fortran/use_mpi_f08/pmpi_f08.tmp + $(mod_verbose)$(F08_COMPILE_MODS) -c `test -f 'src/binding/fortran/use_mpi_f08/pmpi_f08.f90' || echo '$(srcdir)/'`src/binding/fortran/use_mpi_f08/pmpi_f08.f90 -o src/binding/fortran/use_mpi_f08/pmpi_f08.lo + @mv src/binding/fortran/use_mpi_f08/pmpi_f08.tmp src/binding/fortran/use_mpi_f08/pmpi_f08.stamp + +src/binding/fortran/use_mpi_f08/$(PMPI_F08_NAME).$(MOD) src/binding/fortran/use_mpi_f08/pmpi_f08.lo : src/binding/fortran/use_mpi_f08/pmpi_f08.stamp + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi_f08/pmpi_f08-lock src/binding/fortran/use_mpi_f08/pmpi_f08.stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi_f08/pmpi_f08-lock 2>/dev/null; then \ + rm -f src/binding/fortran/use_mpi_f08/pmpi_f08.stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi_f08/pmpi_f08.stamp; \ + rmdir src/binding/fortran/use_mpi_f08/pmpi_f08-lock; \ + else \ + while test -d src/binding/fortran/use_mpi_f08/pmpi_f08-lock; do sleep 1; done; \ + test -f src/binding/fortran/use_mpi_f08/pmpi_f08.stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi_f08/$(PMPI_F08_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/pmpi_f08.lo \ + src/binding/fortran/use_mpi_f08/pmpi_f08.stamp \ + src/binding/fortran/use_mpi_f08/pmpi_f08.tmp + +src/binding/fortran/use_mpi_f08/mpi_c_interface.stamp: src/binding/fortran/use_mpi_f08/mpi_c_interface.f90 src/binding/fortran/use_mpi_f08/mpi_c_interface_cdesc.stamp + @rm -f src/binding/fortran/use_mpi_f08/mpi_c_interface.tmp + @touch src/binding/fortran/use_mpi_f08/mpi_c_interface.tmp + $(mod_verbose)$(F08_COMPILE_MODS) -c `test -f 'src/binding/fortran/use_mpi_f08/mpi_c_interface.f90' || echo '$(srcdir)/'`src/binding/fortran/use_mpi_f08/mpi_c_interface.f90 -o src/binding/fortran/use_mpi_f08/mpi_c_interface.lo + @mv src/binding/fortran/use_mpi_f08/mpi_c_interface.tmp src/binding/fortran/use_mpi_f08/mpi_c_interface.stamp + +src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_NAME).$(MOD) src/binding/fortran/use_mpi_f08/mpi_c_interface.lo : src/binding/fortran/use_mpi_f08/mpi_c_interface.stamp + @if test -f $@; then :; else \ + trap 'rm -rf src/binding/fortran/use_mpi_f08/mpi_c_interface-lock src/binding/fortran/use_mpi_f08/mpi_c_interface.stamp' 1 2 13 15; \ + if mkdir src/binding/fortran/use_mpi_f08/mpi_c_interface-lock 2>/dev/null; then \ + rm -f src/binding/fortran/use_mpi_f08/mpi_c_interface.stamp; \ + $(MAKE) $(AM_MAKEFLAGS) src/binding/fortran/use_mpi_f08/mpi_c_interface.stamp; \ + rmdir src/binding/fortran/use_mpi_f08/mpi_c_interface-lock; \ + else \ + while test -d src/binding/fortran/use_mpi_f08/mpi_c_interface-lock; do sleep 1; done; \ + test -f src/binding/fortran/use_mpi_f08/mpi_c_interface.stamp; exit $$?; \ + fi; \ + fi + +CLEANFILES += src/binding/fortran/use_mpi_f08/$(MPI_C_INTERFACE_NAME).$(MOD) \ + src/binding/fortran/use_mpi_f08/mpi_c_interface.lo \ + src/binding/fortran/use_mpi_f08/mpi_c_interface.stamp \ + src/binding/fortran/use_mpi_f08/mpi_c_interface.tmp + +endif BUILD_F08_BINDING diff --git a/src/binding/abi_fortran/use_mpi_f08/mpi_c_interface.f90 b/src/binding/abi_fortran/use_mpi_f08/mpi_c_interface.f90 new file mode 100644 index 00000000000..52b24bcd722 --- /dev/null +++ b/src/binding/abi_fortran/use_mpi_f08/mpi_c_interface.f90 @@ -0,0 +1,11 @@ +! +! Copyright (C) by Argonne National Laboratory +! See COPYRIGHT in top-level directory +! + +module mpi_c_interface + use mpi_c_interface_types + use mpi_c_interface_nobuf + use mpi_c_interface_cdesc + use mpi_c_interface_glue +end module mpi_c_interface diff --git a/src/binding/abi_fortran/use_mpi_f08/mpi_c_interface_glue.f90 b/src/binding/abi_fortran/use_mpi_f08/mpi_c_interface_glue.f90 new file mode 100644 index 00000000000..6f14bf7e625 --- /dev/null +++ b/src/binding/abi_fortran/use_mpi_f08/mpi_c_interface_glue.f90 @@ -0,0 +1,92 @@ +! +! Copyright (C) by Argonne National Laboratory +! See COPYRIGHT in top-level directory +! + +module mpi_c_interface_glue + +use, intrinsic :: iso_c_binding, only : c_char, C_NULL_CHAR + +implicit none + +public :: MPIR_Fortran_string_f2c +public :: MPIR_Fortran_string_c2f + +public :: MPIR_Grequest_set_lang_fortran +public :: MPII_Keyval_set_f90_proxy + +! Bind to C's enum MPIR_Attr_type in mpir_attr_generic.h +enum, bind(C) + enumerator :: MPIR_ATTR_PTR = 0 + enumerator :: MPIR_ATTR_AINT = 1 + enumerator :: MPIR_ATTR_INT = 3 +end enum + +interface + +! Just need to tag the lang is Fortran, so it is fine to bind to *_lang_f77 +subroutine MPIR_Grequest_set_lang_fortran(request) bind(C, name="MPII_Grequest_set_lang_f77") + use :: mpi_c_interface_types, only : c_Request + integer(c_Request), value, intent(in) :: request + ! The subroutine is implemented in mpir_request.c on the C side +end subroutine MPIR_Grequest_set_lang_fortran + +subroutine MPII_Keyval_set_f90_proxy(keyval) bind(C, name="MPII_Keyval_set_f90_proxy") + use :: iso_c_binding, only : c_int + integer(c_int), value, intent(in) :: keyval + ! The subroutine is implemented in mpif_h/attr_proxy.c on the C side +end subroutine + +end interface + +contains + +! Copy Fortran string to C character array, assuming the C array is one-char +! longer for the terminating null char. +! fstring : the Fortran input string +! cstring : the C output string (with memory already allocated) +subroutine MPIR_Fortran_string_f2c(fstring, cstring) + implicit none + character(len=*), intent(in) :: fstring + character(kind=c_char), intent(out) :: cstring(:) + integer :: i, j + logical :: met_non_blank + + ! Trim the leading and trailing blank characters + j = 1 + met_non_blank = .false. + do i = 1, len_trim(fstring) + if (met_non_blank) then + cstring(j) = fstring(i:i) + j = j + 1 + else if (fstring(i:i) /= ' ') then + met_non_blank = .true. + cstring(j) = fstring(i:i) + j = j + 1 + end if + end do + + cstring(j) = C_NULL_CHAR +end subroutine MPIR_Fortran_string_f2c + +! Copy C character array to Fortran string +subroutine MPIR_Fortran_string_c2f(cstring, fstring) + implicit none + character(kind=c_char), intent(in) :: cstring(:) + character(len=*), intent(out) :: fstring + integer :: i, j, length + + i = 1 + do while (cstring(i) /= C_NULL_CHAR) + fstring(i:i) = cstring(i) + i = i + 1 + end do + + ! Zero out the trailing characters + length = len(fstring) + do j = i, length + fstring(j:j) = ' ' + end do +end subroutine MPIR_Fortran_string_c2f + +end module mpi_c_interface_glue diff --git a/src/binding/abi_fortran/use_mpi_f08/mpi_c_interface_types.f90.in b/src/binding/abi_fortran/use_mpi_f08/mpi_c_interface_types.f90.in new file mode 100644 index 00000000000..63e11d28ac7 --- /dev/null +++ b/src/binding/abi_fortran/use_mpi_f08/mpi_c_interface_types.f90.in @@ -0,0 +1,59 @@ +! +! Copyright (C) by Argonne National Laboratory +! See COPYRIGHT in top-level directory +! +! Module mpi_c_interface_types is a helper module used by the modules +! specifying c interfaces: +! +! mpi_c_interface_cdesc - interfaces for MPI functions with a descriptor argument +! mpi_c_interface_nobuf - interfaces for MPI functions with no choice argument +! +! MPICH C interface uses integer for handles and status type. +! It is not defined in the spec and not intended for end users. +!-------------------------------------------------------------- + +module mpi_c_interface_types + +use, intrinsic :: iso_c_binding + +implicit none + +integer,parameter :: c_Fint = KIND(0) + +integer,parameter :: c_Aint = @F08_C_AINT@ +integer,parameter :: c_Count = @F08_C_COUNT@ +integer,parameter :: c_Offset = @F08_C_OFFSET@ + +!============================================================= +! Kinds for handle types in C prototypes; should match mpi.h +!============================================================= + +integer,parameter :: c_Datatype = c_int +integer,parameter :: c_Comm = c_int +integer,parameter :: c_Group = c_int +integer,parameter :: c_Win = c_int +integer,parameter :: c_Op = c_int +integer,parameter :: c_Info = c_int +integer,parameter :: c_Errhandler = c_int +integer,parameter :: c_Request = c_int +integer,parameter :: c_Message = c_int +integer,parameter :: c_Session = c_int +integer,parameter :: c_Stream = c_int +integer,parameter :: c_File = c_intptr_t + +!================================================ +! C struct for STATUS values; should match mpi.h +!================================================ + +! MPI_Status, with name changed to c_Status for internal disambiguation +! A.1.2 p 676 + +type, bind(c) :: c_Status + integer(c_int) :: count_lo + integer(c_int) :: count_hi_and_cancelled + integer(c_int) :: MPI_SOURCE + integer(c_int) :: MPI_TAG + integer(c_int) :: MPI_ERROR +end type c_Status + +end module mpi_c_interface_types diff --git a/src/binding/abi_fortran/use_mpi_f08/mpi_f08_callbacks.f90 b/src/binding/abi_fortran/use_mpi_f08/mpi_f08_callbacks.f90 new file mode 100644 index 00000000000..c8ac95e17ff --- /dev/null +++ b/src/binding/abi_fortran/use_mpi_f08/mpi_f08_callbacks.f90 @@ -0,0 +1,349 @@ +! +! Copyright (C) by Argonne National Laboratory +! See COPYRIGHT in top-level directory +! + +module mpi_f08_callbacks + +! MPI3.0, A.1.3, p. 678 + +public :: MPI_COMM_DUP_FN +public :: MPI_COMM_NULL_COPY_FN +public :: MPI_COMM_NULL_DELETE_FN +public :: MPI_TYPE_DUP_FN +public :: MPI_TYPE_NULL_COPY_FN +public :: MPI_TYPE_NULL_DELETE_FN +public :: MPI_WIN_DUP_FN +public :: MPI_WIN_NULL_COPY_FN +public :: MPI_WIN_NULL_DELETE_FN +public :: MPI_CONVERSION_FN_NULL + +abstract interface + +subroutine MPI_User_function(invec, inoutvec, len, datatype) + use, intrinsic :: iso_c_binding, only : c_ptr + use mpi_f08_types, only : MPI_Datatype + implicit none + type(c_ptr), value :: invec, inoutvec + integer :: len + type(MPI_Datatype) :: datatype +end subroutine + +subroutine MPI_User_function_c(invec, inoutvec, len, datatype) + use, intrinsic :: iso_c_binding, only : c_ptr + use mpi_f08_types, only : MPI_Datatype + use mpi_f08_compile_constants, only : MPI_COUNT_KIND + implicit none + type(c_ptr), value :: invec, inoutvec + integer(kind=MPI_COUNT_KIND) :: len + type(MPI_Datatype) :: datatype +end subroutine + +subroutine MPI_Comm_copy_attr_function(oldcomm,comm_keyval,extra_state, & + attribute_val_in,attribute_val_out,flag,ierror) + use mpi_f08_types, only : MPI_Comm + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND + implicit none + type(MPI_Comm) :: oldcomm + integer :: comm_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: extra_state, attribute_val_in, attribute_val_out + logical :: flag +end subroutine + +subroutine MPI_Comm_delete_attr_function(comm,comm_keyval, & + attribute_val, extra_state, ierror) + use mpi_f08_types, only : MPI_Comm + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND + implicit none + type(MPI_Comm) :: comm + integer :: comm_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: attribute_val, extra_state +end subroutine + +subroutine MPI_Win_copy_attr_function(oldwin,win_keyval,extra_state, & + attribute_val_in,attribute_val_out,flag,ierror) + use mpi_f08_types, only : MPI_Win + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND + implicit none + type(MPI_Win) :: oldwin + integer :: win_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: extra_state, attribute_val_in, attribute_val_out + logical :: flag +end subroutine + +subroutine MPI_Win_delete_attr_function(win,win_keyval,attribute_val, & + extra_state,ierror) + use mpi_f08_types, only : MPI_Win + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND + implicit none + type(MPI_Win) :: win + integer :: win_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: attribute_val, extra_state +end subroutine + +subroutine MPI_Type_copy_attr_function(oldtype,type_keyval,extra_state, & + attribute_val_in,attribute_val_out,flag,ierror) + use mpi_f08_types, only : MPI_Datatype + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND + implicit none + type(MPI_Datatype) :: oldtype + integer :: type_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: extra_state, attribute_val_in, attribute_val_out + logical :: flag +end subroutine + +subroutine MPI_Type_delete_attr_function(datatype,type_keyval, & + attribute_val,extra_state,ierror) + use mpi_f08_types, only : MPI_Datatype + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND + implicit none + type(MPI_Datatype) :: datatype + integer :: type_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: attribute_val, extra_state +end subroutine + +subroutine MPI_Comm_errhandler_function(comm,error_code) + use mpi_f08_types, only : MPI_Comm + implicit none + type(MPI_Comm) :: comm + integer :: error_code +end subroutine + +subroutine MPI_Win_errhandler_function(win, error_code) + use mpi_f08_types, only : MPI_Win + implicit none + type(MPI_Win) :: win + integer :: error_code +end subroutine + +subroutine MPI_Session_errhandler_function(session, error_code) + use mpi_f08_types, only : MPI_Session + implicit none + type(MPI_Session) :: session + integer :: error_code +end subroutine + +subroutine MPI_File_errhandler_function(file, error_code) + use mpi_f08_types, only : MPI_File + implicit none + type(MPI_File) :: file + integer :: error_code +end subroutine + +subroutine MPI_Grequest_query_function(extra_state,status,ierror) + use mpi_f08_types, only : MPI_Status + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND + implicit none + type(MPI_Status) :: status + integer :: ierror + integer(kind=MPI_ADDRESS_KIND) :: extra_state +end subroutine + +subroutine MPI_Grequest_free_function(extra_state,ierror) + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND + implicit none + integer :: ierror + integer(kind=MPI_ADDRESS_KIND) :: extra_state +end subroutine + +subroutine MPI_Grequest_cancel_function(extra_state,complete,ierror) + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND + implicit none + integer(kind=MPI_ADDRESS_KIND) :: extra_state + logical :: complete + integer :: ierror +end subroutine + +subroutine MPI_Datarep_extent_function(datatype, extent, extra_state, ierror) + use mpi_f08_types, only : MPI_Datatype + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND + implicit none + type(MPI_Datatype) :: datatype + integer :: ierror + integer(kind=MPI_ADDRESS_KIND) :: extent, extra_state +end subroutine + +subroutine MPI_Datarep_conversion_function(userbuf, datatype, count, & + filebuf, position, extra_state, ierror) + use, intrinsic :: iso_c_binding, only : c_ptr + use mpi_f08_types, only : MPI_Datatype + use mpi_f08_compile_constants, only : MPI_OFFSET_KIND, MPI_ADDRESS_KIND + implicit none + type(c_ptr), value :: userbuf, filebuf + type(MPI_Datatype) :: datatype + integer :: count, ierror + integer(kind=MPI_OFFSET_KIND) :: position + integer(kind=MPI_ADDRESS_KIND) :: extra_state +end subroutine + +subroutine MPI_Datarep_conversion_function_c(userbuf, datatype, count, & + filebuf, position, extra_state, ierror) + use, intrinsic :: iso_c_binding, only : c_ptr + use mpi_f08_types, only : MPI_Datatype + use mpi_f08_compile_constants, only : MPI_OFFSET_KIND, MPI_ADDRESS_KIND, MPI_COUNT_KIND + implicit none + type(c_ptr), value :: userbuf, filebuf + type(MPI_Datatype) :: datatype + integer :: ierror + integer(kind=MPI_COUNT_KIND) :: count + integer(kind=MPI_OFFSET_KIND) :: position + integer(kind=MPI_ADDRESS_KIND) :: extra_state +end subroutine + +end interface + +contains + +! See p.269, MPI 3.0 +subroutine MPI_COMM_DUP_FN(oldcomm,comm_keyval,extra_state, & + attribute_val_in,attribute_val_out,flag,ierror) + use mpi_f08_types, only : MPI_Comm + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND, MPI_SUCCESS + implicit none + type(MPI_Comm) :: oldcomm + integer :: comm_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: extra_state, attribute_val_in, attribute_val_out + logical :: flag + + flag = .true. + attribute_val_out = attribute_val_in + ierror = MPI_SUCCESS +end subroutine + +subroutine MPI_COMM_NULL_COPY_FN(oldcomm,comm_keyval,extra_state, & + attribute_val_in,attribute_val_out,flag,ierror) + use mpi_f08_types, only : MPI_Comm + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND, MPI_SUCCESS + implicit none + type(MPI_Comm) :: oldcomm + integer :: comm_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: extra_state, attribute_val_in, attribute_val_out + logical :: flag + + flag = .false. + ierror = MPI_SUCCESS +end subroutine + +subroutine MPI_COMM_NULL_DELETE_FN(comm,comm_keyval, & + attribute_val, extra_state, ierror) + use mpi_f08_types, only : MPI_Comm + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND, MPI_SUCCESS + implicit none + type(MPI_Comm) :: comm + integer :: comm_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: attribute_val, extra_state + + ierror = MPI_SUCCESS +end subroutine + +subroutine MPI_TYPE_DUP_FN(oldtype,type_keyval,extra_state, & + attribute_val_in,attribute_val_out,flag,ierror) + use mpi_f08_types, only : MPI_Datatype + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND, MPI_SUCCESS + implicit none + type(MPI_Datatype) :: oldtype + integer :: type_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: extra_state, attribute_val_in, attribute_val_out + logical :: flag + + flag = .true. + attribute_val_out = attribute_val_in + ierror = MPI_SUCCESS +end subroutine + +subroutine MPI_TYPE_NULL_COPY_FN(oldtype,type_keyval,extra_state, & + attribute_val_in,attribute_val_out,flag,ierror) + use mpi_f08_types, only : MPI_Datatype + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND, MPI_SUCCESS + implicit none + type(MPI_Datatype) :: oldtype + integer :: type_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: extra_state, attribute_val_in, attribute_val_out + logical :: flag + + flag = .false. + ierror = MPI_SUCCESS +end subroutine + +subroutine MPI_TYPE_NULL_DELETE_FN(datatype,type_keyval, & + attribute_val, extra_state, ierror) + use mpi_f08_types, only : MPI_Datatype + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND, MPI_SUCCESS + implicit none + type(MPI_Datatype) :: datatype + integer :: type_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: attribute_val, extra_state + + ierror = MPI_SUCCESS +end subroutine + +subroutine MPI_WIN_DUP_FN(oldwin,win_keyval,extra_state, & + attribute_val_in,attribute_val_out,flag,ierror) + use mpi_f08_types, only : MPI_Win + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND, MPI_SUCCESS + implicit none + type(MPI_Win) :: oldwin + integer :: win_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: extra_state, attribute_val_in, attribute_val_out + logical :: flag + + flag = .true. + attribute_val_out = attribute_val_in + ierror = MPI_SUCCESS +end subroutine + +subroutine MPI_WIN_NULL_COPY_FN(oldwin,win_keyval,extra_state, & + attribute_val_in,attribute_val_out,flag,ierror) + use mpi_f08_types, only : MPI_Win + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND, MPI_SUCCESS + implicit none + type(MPI_Win) :: oldwin + integer :: win_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: extra_state, attribute_val_in, attribute_val_out + logical :: flag + + flag = .false. + ierror = MPI_SUCCESS +end subroutine + +subroutine MPI_WIN_NULL_DELETE_FN(win,win_keyval, & + attribute_val, extra_state, ierror) + use mpi_f08_types, only : MPI_Win + use mpi_f08_compile_constants, only : MPI_ADDRESS_KIND, MPI_SUCCESS + implicit none + type(MPI_Win) :: win + integer :: win_keyval, ierror + integer(kind=MPI_ADDRESS_KIND) :: attribute_val, extra_state + + ierror = MPI_SUCCESS +end subroutine + +subroutine MPI_CONVERSION_FN_NULL(userbuf, datatype, count, & + filebuf, position, extra_state, ierror) + use, intrinsic :: iso_c_binding, only : c_ptr + use mpi_f08_types, only : MPI_Datatype + use mpi_f08_compile_constants, only : MPI_OFFSET_KIND, MPI_ADDRESS_KIND + implicit none + type(c_ptr), value :: userbuf, filebuf + type(MPI_Datatype) :: datatype + integer :: count, ierror + integer(kind=MPI_OFFSET_KIND) :: position + integer(kind=MPI_ADDRESS_KIND) :: extra_state + ! Do nothing +end subroutine + +subroutine MPI_CONVERSION_FN_NULL_C(userbuf, datatype, count, & + filebuf, position, extra_state, ierror) + use, intrinsic :: iso_c_binding, only : c_ptr + use mpi_f08_types, only : MPI_Datatype + use mpi_f08_compile_constants, only : MPI_OFFSET_KIND, MPI_ADDRESS_KIND, MPI_COUNT_KIND + implicit none + type(c_ptr), value :: userbuf, filebuf + type(MPI_Datatype) :: datatype + integer(kind=MPI_COUNT_KIND) :: count, ierror + integer(kind=MPI_OFFSET_KIND) :: position + integer(kind=MPI_ADDRESS_KIND) :: extra_state + ! Do nothing +end subroutine + +end module mpi_f08_callbacks diff --git a/src/binding/abi_fortran/use_mpi_f08/mpi_f08_link_constants.f90 b/src/binding/abi_fortran/use_mpi_f08/mpi_f08_link_constants.f90 new file mode 100644 index 00000000000..454d0f8449b --- /dev/null +++ b/src/binding/abi_fortran/use_mpi_f08/mpi_f08_link_constants.f90 @@ -0,0 +1,140 @@ +! +! Copyright (C) by Argonne National Laboratory +! See COPYRIGHT in top-level directory +! + +module mpi_f08_link_constants +use, intrinsic :: iso_c_binding, only: c_ptr, c_int, c_char, c_loc +use :: mpi_f08_types, only : MPI_Status +use :: mpi_c_interface_types, only : c_Status + +implicit none + +! Named link time constants + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! +! MPI_STATUS_IGNORE, MPI_STATUSES_IGNORE +! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +! In MPICH C code, MPI_STATUS_IGNORE, MPI_STATUSES_IGNORE are pointers of bad address + +! Fortran programmers use these MPI_Status variables for INOUT status arguments +type(MPI_Status), bind(C, name="MPIR_F08_MPI_STATUS_IGNORE_OBJ"), target :: MPI_STATUS_IGNORE +type(MPI_Status), dimension(1), bind(C, name="MPIR_F08_MPI_STATUSES_IGNORE_OBJ"), target :: MPI_STATUSES_IGNORE + + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! +! MPI_ARGV_NULL, MPI_ARGVS_NULL +! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! In MPICH C code, MPI_ARGV_NULL and MPI_ARGVS_NULL are NULL pointers +character(len=1), dimension(1), target :: MPI_ARGV_NULL +character(len=1), dimension(1,1), target :: MPI_ARGVS_NULL + + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! +! MPI_ERRCODES_IGNORE +! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +integer, dimension(1), target :: MPI_ERRCODES_IGNORE + + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! +! MPI_UNWEIGHTED, MPI_WEIGHTS_EMPTY +! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! Type of MPI_UNWEIGHTED and MPI_WEIGHTS_EMPTY is not integer(c_int) since we only care their address + +integer, dimension(1), target :: MPI_UNWEIGHTED +integer, dimension(1), target :: MPI_WEIGHTS_EMPTY + + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! +! MPI_BUFFER_AUTOMATIC +! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +integer, dimension(1), target :: MPI_BUFFER_AUTOMATIC + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! +! MPI_IN_PLACE +! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +integer(c_int), bind(C, name="MPIR_F08_MPI_IN_PLACE"), target :: MPI_IN_PLACE + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! +! MPI_BOTTOM +! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! Buffer Address Constants +! A.1.1 p. 663 +integer(c_int), bind(C, name="MPIR_F08_MPI_BOTTOM"), target :: MPI_BOTTOM + +INTERFACE + +FUNCTION MPIR_F08_get_MPI_STATUS_IGNORE_c() & + bind (C, name="MPIR_F08_get_MPI_STATUS_IGNORE") result(p) + USE, intrinsic :: iso_c_binding, ONLY : c_ptr + IMPLICIT NONE + TYPE(c_ptr) :: p +END FUNCTION + +FUNCTION MPIR_F08_get_MPI_STATUSES_IGNORE_c() & + bind (C, name="MPIR_F08_get_MPI_STATUSES_IGNORE") result(p) + USE, intrinsic :: iso_c_binding, ONLY : c_ptr + IMPLICIT NONE + TYPE(c_ptr) :: p +END FUNCTION + +FUNCTION MPIR_F08_get_MPI_ARGV_NULL_c() & + bind (C, name="MPIR_F08_get_MPI_ARGV_NULL") result(p) + USE, intrinsic :: iso_c_binding, ONLY : c_ptr + IMPLICIT NONE + TYPE(c_ptr) :: p +END FUNCTION + +FUNCTION MPIR_F08_get_MPI_ARGVS_NULL_c() & + bind (C, name="MPIR_F08_get_MPI_ARGVS_NULL") result(p) + USE, intrinsic :: iso_c_binding, ONLY : c_ptr + IMPLICIT NONE + TYPE(c_ptr) :: p +END FUNCTION + +FUNCTION MPIR_F08_get_MPI_ERRCODES_IGNORE_c() & + bind (C, name="MPIR_F08_get_MPI_ERRCODES_IGNORE") result(p) + USE, intrinsic :: iso_c_binding, ONLY : c_ptr + IMPLICIT NONE + TYPE(c_ptr) :: p +END FUNCTION + +FUNCTION MPIR_F08_get_MPI_UNWEIGHTED_c() & + bind (C, name="MPIR_F08_get_MPI_UNWEIGHTED") result(p) + USE, intrinsic :: iso_c_binding, ONLY : c_ptr + IMPLICIT NONE + TYPE(c_ptr) :: p +END FUNCTION + +FUNCTION MPIR_F08_get_MPI_WEIGHTS_EMPTY_c() & + bind (C, name="MPIR_F08_get_MPI_WEIGHTS_EMPTY") result(p) + USE, intrinsic :: iso_c_binding, ONLY : c_ptr + IMPLICIT NONE + TYPE(c_ptr) :: p +END FUNCTION + +FUNCTION MPIR_F08_get_MPI_BUFFER_AUTOMATIC_c() & + bind (C, name="MPIR_F08_get_MPI_BUFFER_AUTOMATIC") result(p) + USE, intrinsic :: iso_c_binding, ONLY : c_ptr + IMPLICIT NONE + TYPE(c_ptr) :: p +END FUNCTION + +END INTERFACE + +end module mpi_f08_link_constants diff --git a/src/binding/abi_fortran/use_mpi_f08/wrappers_c/cdesc.c b/src/binding/abi_fortran/use_mpi_f08/wrappers_c/cdesc.c new file mode 100644 index 00000000000..9d8d9120297 --- /dev/null +++ b/src/binding/abi_fortran/use_mpi_f08/wrappers_c/cdesc.c @@ -0,0 +1,107 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +#include "cdesc.h" +#include +#include + +/* Fortran 2008 specifies a maximum rank of 15 */ +#define MAX_RANK (15) + +int cdesc_create_datatype(CFI_cdesc_t * cdesc, MPI_Aint oldcount, MPI_Datatype oldtype, + MPI_Datatype * newtype) +{ + MPI_Datatype types[MAX_RANK + 1]; /* Use a fixed size array to avoid malloc. + 1 for oldtype */ + int mpi_errno = MPI_SUCCESS; + int accum_elems = 1; + int accum_sm = cdesc->elem_len; + int done = 0; /* Have we created a datatype for oldcount of oldtype? */ + int last; /* Index of the last successfully created datatype in types[] */ + int extent; + int i, j; + +#ifdef HAVE_ERROR_CHECKING + { + int size; + assert(cdesc->rank <= MAX_RANK); + PMPI_Type_size(oldtype, &size); + /* When cdesc->elem_len != size, things suddenly become complicated. Generally, it is hard to create + * a composite datatype based on two datatypes. Currently we don't support it and doubt it is useful. + */ + assert(cdesc->elem_len == size); + } +#endif + + types[0] = oldtype; + i = 0; + done = 0; + while (i < cdesc->rank && !done) { + if (oldcount % accum_elems) { + /* oldcount should be a multiple of accum_elems, otherwise we might need an + * MPI indexed datatype to describle the irregular region, which is not supported yet. + */ + mpi_errno = MPI_ERR_INTERN; + last = 0; + goto fn_fail; + } + + extent = oldcount / accum_elems; + if (extent > cdesc->dim[i].extent) { + extent = cdesc->dim[i].extent; + } else { + /* Up to now, we have accumulated enough elements */ + done = 1; + } + + if (extent <= INT_MAX) { + if (cdesc->dim[i].sm == accum_sm) { + mpi_errno = PMPI_Type_contiguous(extent, types[i], &types[i + 1]); + } else { + mpi_errno = PMPI_Type_create_hvector(extent, 1, cdesc->dim[i].sm, + types[i], &types[i + 1]); + } + } else { + if (cdesc->dim[i].sm == accum_sm) { + mpi_errno = PMPI_Type_contiguous_c(extent, types[i], &types[i + 1]); + } else { + mpi_errno = PMPI_Type_create_hvector_c(extent, 1, cdesc->dim[i].sm, + types[i], &types[i + 1]); + } + } + if (mpi_errno != MPI_SUCCESS) { + last = i; + goto fn_fail; + } + + mpi_errno = PMPI_Type_commit(&types[i + 1]); + if (mpi_errno != MPI_SUCCESS) { + last = i + 1; + goto fn_fail; + } + + accum_sm = cdesc->dim[i].sm * cdesc->dim[i].extent; + accum_elems *= cdesc->dim[i].extent; + i++; + } + + if (done) { + *newtype = types[i]; + last = i - 1; /* To avoid freeing newtype */ + } else { + /* If # of elements given by "oldcount oldtype" is bigger than + * what cdesc describles, then we will reach here. + */ + last = i; + mpi_errno = MPI_ERR_ARG; + goto fn_fail; + } + + fn_exit: + for (j = 1; j <= last; j++) + PMPI_Type_free(&types[j]); + return mpi_errno; + fn_fail: + goto fn_exit; +} diff --git a/src/binding/abi_fortran/use_mpi_f08/wrappers_c/cdesc.h b/src/binding/abi_fortran/use_mpi_f08/wrappers_c/cdesc.h new file mode 100644 index 00000000000..dedb8127280 --- /dev/null +++ b/src/binding/abi_fortran/use_mpi_f08/wrappers_c/cdesc.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +#ifndef CDESC_H_INCLUDED +#define CDESC_H_INCLUDED + +#include "mpichconf.h" +#include +#include +#include +#include +#include "cdesc_proto.h" + +#ifndef HAVE_ROMIO +#define MPIO_Request MPI_Request +#endif + +extern int MPIR_F08_MPI_IN_PLACE; +extern int MPIR_F08_MPI_BOTTOM; + +extern int cdesc_create_datatype(CFI_cdesc_t * cdesc, MPI_Aint oldcount, MPI_Datatype oldtype, + MPI_Datatype * newtype); +extern int MPIR_Fortran_array_of_string_f2c(const char *strs_f, char ***strs_c, int str_len, + int know_size, int size); +extern int MPIR_Comm_spawn_c(const char *command, char *argv_f, int maxprocs, MPI_Info info, + int root, MPI_Comm comm, MPI_Comm * intercomm, int *array_of_errcodes, + int argv_elem_len); +extern int MPIR_Comm_spawn_multiple_c(int count, char *array_of_commands_f, char *array_of_argv_f, + const int *array_of_maxprocs, const MPI_Info * array_of_info, + int root, MPI_Comm comm, MPI_Comm * intercomm, + int *array_of_errcodes, int commands_elem_len, + int argv_elem_len); + +void *MPIR_F08_get_MPI_STATUS_IGNORE(void); +void *MPIR_F08_get_MPI_STATUSES_IGNORE(void); +void *MPIR_F08_get_MPI_ARGV_NULL(void); +void *MPIR_F08_get_MPI_ARGVS_NULL(void); +void *MPIR_F08_get_MPI_ERRCODES_IGNORE(void); +void *MPIR_F08_get_MPI_UNWEIGHTED(void); +void *MPIR_F08_get_MPI_WEIGHTS_EMPTY(void); +void *MPIR_F08_get_MPI_BUFFER_AUTOMATIC(void); + +#endif /* CDESC_H_INCLUDED */ diff --git a/src/binding/abi_fortran/use_mpi_f08/wrappers_c/comm_spawn_c.c b/src/binding/abi_fortran/use_mpi_f08/wrappers_c/comm_spawn_c.c new file mode 100644 index 00000000000..e9cb9e9138a --- /dev/null +++ b/src/binding/abi_fortran/use_mpi_f08/wrappers_c/comm_spawn_c.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +#include "cdesc.h" + +int MPIR_Comm_spawn_c(const char *command, char *argv_f, int maxprocs, MPI_Info info, int root, + MPI_Comm comm, MPI_Comm * intercomm, int *array_of_errcodes, + int argv_elem_len) +{ + int mpi_errno = MPI_SUCCESS; + char **argv_c = NULL; + + if ((char **) argv_f == MPI_ARGV_NULL) { + argv_c = MPI_ARGV_NULL; + } else { + mpi_errno = MPIR_Fortran_array_of_string_f2c(argv_f, &argv_c, argv_elem_len, + 0 /* Don't know size of argv_f */ , 0); + if (mpi_errno != MPI_SUCCESS) + goto fn_fail; + } + + mpi_errno = + PMPI_Comm_spawn(command, argv_c, maxprocs, info, root, comm, intercomm, array_of_errcodes); + + if (argv_c != MPI_ARGV_NULL) { + free(argv_c); + } + + fn_exit: + return mpi_errno; + fn_fail: + goto fn_exit; +} diff --git a/src/binding/abi_fortran/use_mpi_f08/wrappers_c/comm_spawn_multiple_c.c b/src/binding/abi_fortran/use_mpi_f08/wrappers_c/comm_spawn_multiple_c.c new file mode 100644 index 00000000000..1860d82af63 --- /dev/null +++ b/src/binding/abi_fortran/use_mpi_f08/wrappers_c/comm_spawn_multiple_c.c @@ -0,0 +1,129 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +#include "cdesc.h" +#include + +int MPIR_Comm_spawn_multiple_c(int count, char *array_of_commands_f, + char *array_of_argv_f, const int *array_of_maxprocs, + const MPI_Info * array_of_info, int root, MPI_Comm comm, + MPI_Comm * intercomm, int *array_of_errcodes, + int commands_elem_len, int argv_elem_len) +{ + int mpi_errno = MPI_SUCCESS; + char **array_of_commands_c = NULL; + char ***array_of_argv_c = NULL; + int i, j, offset, len, terminate; + char *buf, *newbuf; + + /* array_of_commands_f in Fortran has type CHARACTER(LEN=*), INTENT(IN) :: array_of_commands(*). + * It contains commands array_of_commands(1), ..., array_of_commands(count). Each is a Fortran + * string of length commands_elem_len, which equals to len(array_of_commands). + * + * We need to convert array_of_commands_f into array_of_commands_c, which in C has type + * char* array_of_commands_c[count], in other words, each element is a pointer to string. + */ + mpi_errno = MPIR_Fortran_array_of_string_f2c(array_of_commands_f, &array_of_commands_c, + commands_elem_len, + 1 /* size of array_of_commands_f is known */ , + count); + if (mpi_errno != MPI_SUCCESS) + goto fn_fail; + + /* array_of_argv_f in Fortran has type CHARACTER(LEN=*), INTENT(IN) :: array_of_argv(count, *). + * For a particular command number K (in the range 1..count), array_of_argv (K, 1) is the first + * argument, array_of_argv(K,2) is the second argument, ... etc., until you get to array_of_argv(K,J) + * being a string of all blank characters. That indicates that command K has J-1 arguments. + * The value of J might be different from each command, but the size of the second dimension of + * array_of_argv is the largest value of J for all the commands. The actual memory layout of + * the array is (arg1 for command 1) (arg1 for command 2) ... (arg1 for command COUNT) + * (arg2 for command 1) ... + * + * We need to convert array_of_argv_f into array_of_argv_c, which in C has type + * char** array_of_argv_c[count], with each element pointing to an array of pointers. + * For example, array_of_argv_c[0] points to an array of pointers to string. + * array_of_argv_c[0][0] points to 1st arg of command 0. array_of_argv_c[0][0] points + * to 2nd arg of command 0, etc. If array_of_argv_c[0][J] is NULL, then command 0 + * has J args. + */ + + if ((char ***) array_of_argv_f == MPI_ARGVS_NULL) { + array_of_argv_c = MPI_ARGVS_NULL; + } else { + array_of_argv_c = (char ***) malloc(sizeof(char **) * count); + if (!array_of_argv_c) { + mpi_errno = MPI_ERR_OTHER; + goto fn_fail; + } + + /* Allocate a temp buf to put args of a command */ + len = 256; /* length of buf. Initialized with an arbitrary value */ + buf = (char *) malloc(sizeof(char) * len); + if (!buf) { + mpi_errno = MPI_ERR_OTHER; + goto fn_fail; + } + + for (i = 0; i < count; i++) { + /* Extract args of command i, and put them in buf */ + char *arg; + offset = 0; /* offset in bytes in buf to put next arg */ + arg = array_of_argv_f + argv_elem_len * i; /* Point to 1st arg of command i */ + do { + if (offset + argv_elem_len > len) { /* Make sure buf is big enough */ + len = offset + argv_elem_len; + newbuf = (char *) realloc(buf, len); + if (!newbuf) { + free(buf); + mpi_errno = MPI_ERR_OTHER; + goto fn_fail; + } + buf = newbuf; + } + + /* Check if arg is a terminating blank string */ + j = 0; + while (arg[j] == ' ' && j < argv_elem_len) + j++; + terminate = (j == argv_elem_len); + + strncpy(buf + offset, arg, argv_elem_len); /* Copy it even it is all blank */ + arg += argv_elem_len * count; /* Move to next arg of command i */ + offset += argv_elem_len; + } while (!terminate); + + /* Convert the args into C style. We indicate we don't know the count of strings so + * that a NULL pointer will be appended at the end. + */ + mpi_errno = + MPIR_Fortran_array_of_string_f2c(buf, &(array_of_argv_c[i]), argv_elem_len, 0, 0); + if (mpi_errno != MPI_SUCCESS) { + for (j = i - 1; j >= 0; j--) + free(array_of_argv_c[j]); + free(buf); + goto fn_fail; + } + } + + free(buf); + } + + mpi_errno = PMPI_Comm_spawn_multiple(count, array_of_commands_c, array_of_argv_c, + array_of_maxprocs, array_of_info, root, comm, intercomm, + array_of_errcodes); + + free(array_of_commands_c); + + if (array_of_argv_c != MPI_ARGVS_NULL) { + for (i = 0; i < count; i++) + free(array_of_argv_c[i]); + free(array_of_argv_c); + } + + fn_exit: + return mpi_errno; + fn_fail: + goto fn_exit; +} diff --git a/src/binding/abi_fortran/use_mpi_f08/wrappers_c/utils.c b/src/binding/abi_fortran/use_mpi_f08/wrappers_c/utils.c new file mode 100644 index 00000000000..9639bf8fc97 --- /dev/null +++ b/src/binding/abi_fortran/use_mpi_f08/wrappers_c/utils.c @@ -0,0 +1,138 @@ +/* + * Copyright (C) by Argonne National Laboratory + * See COPYRIGHT in top-level directory + */ + +#include "cdesc.h" +#include + +int MPIR_F08_MPI_IN_PLACE MPICH_API_PUBLIC; +int MPIR_F08_MPI_BOTTOM MPICH_API_PUBLIC; + +/* + Convert an array of strings in Fortran Format to an array of strings in C format (i.e., char* a[]). + + IN strs_f: An array of strings in Fortran + OUT strs_c: An array of char* in C + IN str_len: The length of a string, i.e., an element in strs_f[]. + By Fortran convention, all strings have the same length + IN know_size: Indicate if size of strs_f[] is already known. + If it is false, then the last element of strs_f[] is represented by a blank line. + Accordingly, we put a NULL to strs_c[] as the last element of strs_c + This case mimics argv in MPI_Comm_spawn + + If it is true, then 'size' gives the size of strs_f[]. No terminating NULL is needed in strs_c[] + This case mimics array_of_commands in MPI_Comm_spawn_multiple + + IN size: Used only when know_size is true. + + Note: The caller needs to free memory of strs_c +*/ +extern int MPIR_Fortran_array_of_string_f2c(const char *strs_f, char ***strs_c, int str_len, + int know_size, int size) +{ + int mpi_errno = MPI_SUCCESS; + char *buf; + char *cur_start; + int num_chars = 0; /* To count the number of chars to allocate */ + int num_strs = 0; /* To count the number of strings in strs_f[] */ + int reached_the_end = 0; /* Indicate whether we reached the last element in strs_f[] */ + int index; + + while (!reached_the_end) { + for (index = str_len - 1; index >= 0; index--) { /* Trim the trailing blanks */ + if (strs_f[str_len * num_strs + index] != ' ') + break; + } + + num_chars += index + 1; + num_strs++; + + if (know_size) { + if (num_strs == size) + reached_the_end = 1; /* Reached the last element */ + } else if (index < 0) { + reached_the_end = 1; /* Found the terminating blank line */ + } + } + + /* Allocate memory for pointers to strings and the strings themself */ + buf = (char *) malloc(sizeof(char *) * num_strs + sizeof(char) * (num_chars + num_strs)); /* Add \0 for each string */ + if (buf == NULL) { + mpi_errno = MPI_ERR_OTHER; + goto fn_fail; + } + + *strs_c = (char **) buf; + cur_start = (char *) (buf + sizeof(char *) * num_strs); + + /* Scan strs_f[] again to set *strs_c[] */ + reached_the_end = 0; + num_strs = 0; + while (!reached_the_end) { + for (index = str_len - 1; index >= 0; index--) { + if (strs_f[str_len * num_strs + index] != ' ') + break; + } + + strncpy(cur_start, &strs_f[str_len * num_strs], index + 1); /* index may be -1 */ + cur_start[index + 1] = '\0'; + (*strs_c)[num_strs] = cur_start; + cur_start += index + 2; /* Move to start of next string */ + + num_strs++; + + if (know_size) { + if (num_strs == size) + reached_the_end = 1; /* Reached the last element */ + } else if (index < 0) { + reached_the_end = 1; /* Find the terminating blank line */ + (*strs_c)[num_strs - 1] = NULL; /* Rewrite the last pointer as NULL */ + } + } + + fn_exit: + return mpi_errno; + fn_fail: + goto fn_exit; +} + +void *MPIR_F08_get_MPI_STATUS_IGNORE(void) +{ + return (void *) MPI_STATUS_IGNORE; +} + +void *MPIR_F08_get_MPI_STATUSES_IGNORE(void) +{ + return (void *) MPI_STATUSES_IGNORE; +} + +void *MPIR_F08_get_MPI_ARGV_NULL(void) +{ + return (void *) MPI_ARGV_NULL; +} + +void *MPIR_F08_get_MPI_ARGVS_NULL(void) +{ + return (void *) MPI_ARGVS_NULL; +} + +void *MPIR_F08_get_MPI_ERRCODES_IGNORE(void) +{ + return (void *) MPI_ERRCODES_IGNORE; +} + +void *MPIR_F08_get_MPI_UNWEIGHTED(void) +{ + return (void *) MPI_UNWEIGHTED; +} + +void *MPIR_F08_get_MPI_WEIGHTS_EMPTY(void) +{ + return (void *) MPI_WEIGHTS_EMPTY; +} + +void *MPIR_F08_get_MPI_BUFFER_AUTOMATIC(void) +{ + return (void *) MPI_BUFFER_AUTOMATIC; +} From f634812021fa7c2aac16cdb4bde59ff6e7d59d50 Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Fri, 29 Mar 2024 14:36:17 -0500 Subject: [PATCH 5/8] abi_fortran: add build files --- autogen.sh | 3 ++ src/binding/abi_fortran/Makefile.am | 28 ++++++++++++++++ src/binding/abi_fortran/configure.ac | 48 ++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 src/binding/abi_fortran/Makefile.am create mode 100644 src/binding/abi_fortran/configure.ac diff --git a/autogen.sh b/autogen.sh index dcba9e1bcb1..09005a45e16 100755 --- a/autogen.sh +++ b/autogen.sh @@ -323,6 +323,8 @@ fn_copy_confdb_etc() { confdb_dirs="${confdb_dirs} test/mpi/dtpools/confdb" fi + confdb_dirs="${confdb_dirs} src/binding/abi_fortran/confdb" + # all the confdb directories, by various names for destdir in $confdb_dirs ; do sync_external confdb "$destdir" @@ -334,6 +336,7 @@ fn_copy_confdb_etc() { cp -pPR maint/version.m4 src/mpi/romio/version.m4 cp -pPR maint/version.m4 src/pmi/version.m4 cp -pPR maint/version.m4 test/mpi/version.m4 + cp -pPR maint/version.m4 src/binding/abi_fortran/version.m4 fi # Now sanity check that some of the above sync was successful diff --git a/src/binding/abi_fortran/Makefile.am b/src/binding/abi_fortran/Makefile.am new file mode 100644 index 00000000000..abeeec685a5 --- /dev/null +++ b/src/binding/abi_fortran/Makefile.am @@ -0,0 +1,28 @@ +## +## Copyright (C) by Argonne National Laboratory +## See COPYRIGHT in top-level directory +## + +AM_CPPFLAGS = $(MPI_ABI_H_INCLUDE) + +include_HEADERS = mpi_abi_fort.h +lib_LTLIBRARIES = libmpifort_abi.la +modinc_HEADERS = $(mpi_fc_modules) + +libmpifort_abi_la_SOURCES = +libmpifort_abi_la_LDFLAGS = -version-info 1:0:0 +libmpifort_abi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC \ + $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(FC) \ + $(AM_FCFLAGS) $(FCFLAGS) $(libmpifort_abi_la_LDFLAGS) \ + $(LDFLAGS) -o $@ + +convenience_libs = +mpi_abi_lib = -lmpi_abi + +# include mpif_h/Makefile.mk +# include use_mpi/Makefile.mk +# include use_mpi_f08/Makefile.mk + +noinst_LTLIBRARIES = $(convenience_libs) + +libmpifort_abi_la_LIBADD = $(convenience_libs) $(mpi_abi_lib) diff --git a/src/binding/abi_fortran/configure.ac b/src/binding/abi_fortran/configure.ac new file mode 100644 index 00000000000..1f065791cf9 --- /dev/null +++ b/src/binding/abi_fortran/configure.ac @@ -0,0 +1,48 @@ +## +## Copyright (C) by Argonne National Laboratory +## See COPYRIGHT in top-level directory +## + +AC_PREREQ([2.69]) + +m4_include([version.m4]) +AC_INIT([mpifort_abi], + MPICH_VERSION_m4, + [discuss@mpich.org], + [mpifort_abi], + [http://www.mpich.org/]) + +AC_CONFIG_AUX_DIR([confdb]) +AC_CONFIG_MACRO_DIR([confdb]) + +AM_INIT_AUTOMAKE([-Wall -Werror -Wno-portability-recursive foreign 1.12.3 silent-rules subdir-objects]) +AM_MAINTAINER_MODE([enable]) + +AC_PROG_CC +AM_PROG_CC_C_O +PAC_CHECK_VISIBILITY +AC_SUBST(VISIBILITY_CFLAGS) + +AM_PROG_AR + +LT_INIT([]) +# Non-verbose make by default +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +AC_CONFIG_HEADERS([config.h]) + +# suppress default "-g -O2" from AC_PROG_FC +: ${FCFLAGS=""} +AC_PROG_FC + +F77=$FC +FFLAGS=$FCFLAGS +AC_PROG_F77 + +modincdir=$includedir +AC_SUBST(modincdir) + +AC_CONFIG_FILES([ + Makefile +]) +AC_OUTPUT From d2eb5712e408c36124742fe2476903e005a27089 Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Sun, 31 Mar 2024 16:26:48 -0500 Subject: [PATCH 6/8] abi_fortran: port fortran binding implementations Port MPICH's fortran binding implementation to abi_fortran. --- maint/gen_binding_abi_fortran.py | 118 +++ maint/gen_binding_f77.py | 7 + maint/local_python/binding_f77.py | 18 +- src/binding/abi_fortran/Makefile.am | 10 +- src/binding/abi_fortran/configure.ac | 840 +++++++++++++++++++++ src/binding/abi_fortran/mpif_h/Makefile.mk | 42 +- 6 files changed, 994 insertions(+), 41 deletions(-) create mode 100644 maint/gen_binding_abi_fortran.py diff --git a/maint/gen_binding_abi_fortran.py b/maint/gen_binding_abi_fortran.py new file mode 100644 index 00000000000..66738794550 --- /dev/null +++ b/maint/gen_binding_abi_fortran.py @@ -0,0 +1,118 @@ +## +## Copyright (C) by Argonne National Laboratory +## See COPYRIGHT in top-level directory +## + +from local_python import MPI_API_Global as G +from local_python.mpi_api import * +from local_python.binding_common import * +from local_python.binding_f77 import * +from local_python import RE +import os + +def main(): + # currently support -no-real128, -no-mpiio, -aint-is-int + G.parse_cmdline() + + binding_dir = G.get_srcdir_path("src/binding") + f77_dir = "src/binding/abi_fortran/mpif_h" + + func_list = load_C_func_list(binding_dir, True) # suppress noise + + func_list.extend(get_mpiio_func_list()) + func_list.extend(get_f77_dummy_func_list()) + func_list.append(G.FUNCS['mpi_f_sync_reg']) + + # preprocess + for func in func_list: + check_func_directives(func) + func_list = [f for f in func_list if '_skip_fortran' not in f] + + # fortran_binding.c + def has_cptr(func): + for p in func['parameters']: + if p['kind'] == 'C_BUFFER': + return True + return False + + G.out = [] + G.profile_out = [] + for func in func_list: + G.out.append("") + dump_f77_c_func(func) + if has_cptr(func): + dump_f77_c_func(func, True) + + f = "%s/fortran_binding.c" % f77_dir + dump_f77_c_file(f, G.out) + + f = "%s/fortran_profile.h" % f77_dir + dump_f77_c_file(f, G.profile_out) + + # .in files has to be generated in the source tree + if G.is_autogen(): + G.mpih_defines = {} + load_mpi_abi_h("src/binding/abi/mpi_abi.h") + load_mpi_abi_h("src/binding/abi_fortran/mpi_abi_fort.h") + del G.mpih_defines['MPI_ABI_Aint'] + del G.mpih_defines['MPI_ABI_Offset'] + del G.mpih_defines['MPI_ABI_Count'] + del G.mpih_defines['MPI_ABI_Fint'] + G.mpih_defines['MPI_LONG_LONG_INT'] = G.mpih_defines['MPI_LONG_LONG'] + G.mpih_defines['MPI_C_COMPLEX'] = G.mpih_defines['MPI_C_FLOAT_COMPLEX'] + + G.mpih_defines['MPI_INTEGER_KIND'] = 4 + G.mpih_defines['MPI_ADDRESS_KIND'] = 8 + G.mpih_defines['MPI_COUNT_KIND'] = 8 + G.mpih_defines['MPI_OFFSET_KIND'] = 8 + for name in ['INTEGER_KIND', 'ADDRESS_KIND', 'COUNT_KIND', 'OFFSET_KIND']: + if name in os.environ: + G.mpih_defines['MPI_' + name] = os.environ[name] + autoconf_macros = {} + autoconf_macros['FORTRAN_MPI_OFFSET'] = 'INTEGER(KIND=MPI_OFFSET_KIND)' + autoconf_macros['DLLIMPORT'] = '' + + f = "%s/mpif.h" % f77_dir + dump_mpif_h(f, autoconf_macros) + +def load_mpi_abi_h(f): + # load constants into G.mpih_defines + with open(f, "r") as In: + for line in In: + # trim trailing comments + line = re.sub(r'\s+\/\*.*', '', line) + if RE.match(r'#define\s+(MPI_\w+)\s+(.+)', line): + # direct macros + (name, val) = RE.m.group(1, 2) + if RE.match(r'\(+MPI_\w+\)\(?0x([0-9a-fA-F]+)', val): + # handle constants + val = int(RE.m.group(1), 16) + elif RE.match(r'\(+MPI_Offset\)(-?\d+)', val): + # MPI_DISPLACEMENT_CURRENT + val = RE.m.group(1) + elif RE.match(r'0x([0-9a-fA-F]+)', val): + # direct hex constants (KEYVAL constants) + val = int(RE.m.group(1), 16) + if RE.match(r'MPI_(TAG_UB|HOST|IO|WTIME_IS_GLOBAL|UNIVERSE_SIZE|LASTUSEDCODE|APPNUM|WIN_(BASE|SIZE|DISP_UNIT|CREATE_FLAVOR|MODEL))', name): + # KEYVAL, Fortran value is C-value + 1 + val = val + 1 + elif RE.match(r'MPI_MAX_', name): + # Fortran string buffer limit need be 1-less + if re.match(r'@\w+@', val): + val += "-1" + else: + val = int(val) - 1 + elif RE.match(r'\(([-\d]+)\)', val): + # take off the extra parentheses + val = RE.m.group(1) + + G.mpih_defines[name] = val + elif RE.match(r'\s+(MPI_\w+)\s*=\s*(\d+)', line): + # enum values + (name, val) = RE.m.group(1, 2) + G.mpih_defines[name] = val + +# --------------------------------------------------------- +if __name__ == "__main__": + main() + diff --git a/maint/gen_binding_f77.py b/maint/gen_binding_f77.py index c4bbd43c367..449b50aba03 100644 --- a/maint/gen_binding_f77.py +++ b/maint/gen_binding_f77.py @@ -59,6 +59,13 @@ def has_cptr(func): G.mpih_defines = {} load_mpi_h_in("src/include/mpi.h.in") load_mpi_h_in("src/mpi/romio/include/mpio.h.in") + + for a in ['INTEGER', 'ADDRESS', 'COUNT', 'OFFSET']: + G.mpih_defines['MPI_%s_KIND' % a] = '@%s_KIND@' % a + G.mpih_defines['MPI_STATUS_SIZE'] = G.mpih_defines['MPI_F_STATUS_SIZE'] + for a in ['SOURCE', 'TAG', 'ERROR']: + G.mpih_defines['MPI_%s' % a] = int(G.mpih_defines['MPI_F_%s' % a]) + 1 + f = "%s/mpif.h.in" % f77_dir dump_mpif_h(f) diff --git a/maint/local_python/binding_f77.py b/maint/local_python/binding_f77.py index 60bccad864c..69b58624e0d 100644 --- a/maint/local_python/binding_f77.py +++ b/maint/local_python/binding_f77.py @@ -952,19 +952,13 @@ def dump_f77_c_file(f, lines): print(" " * indent, end='', file=Out) print(l, file=Out) -def dump_mpif_h(f): +def dump_mpif_h(f, autoconf_macros={}): print(" --> [%s]" % f) # note: fixed-form Fortran line is ignored after column 72 with open(f, "w") as Out: for l in G.copyright_f77: print(l, file=Out) - for a in ['INTEGER', 'ADDRESS', 'COUNT', 'OFFSET']: - G.mpih_defines['MPI_%s_KIND' % a] = '@%s_KIND@' % a - G.mpih_defines['MPI_STATUS_SIZE'] = G.mpih_defines['MPI_F_STATUS_SIZE'] - for a in ['SOURCE', 'TAG', 'ERROR']: - G.mpih_defines['MPI_%s' % a] = int(G.mpih_defines['MPI_F_%s' % a]) + 1 - # -- all integer constants for name in G.mpih_defines: T = "INTEGER" @@ -977,7 +971,10 @@ def dump_mpif_h(f): elif re.match(r'MPI_(UNWEIGHTED|WEIGHTS_EMPTY|BUFFER_AUTOMATIC|BOTTOM|IN_PLACE|STATUS_IGNORE|STATUSES_IGNORE|ERRCODES_IGNORE|ARGVS_NULL|ARGV_NULL)', name): continue elif re.match(r'MPI_DISPLACEMENT_CURRENT', name): - T = '@FORTRAN_MPI_OFFSET@' + if 'FORTRAN_MPI_OFFSET' in autoconf_macros: + T = autoconf_macros['FORTRAN_MPI_OFFSET'] + else: + T = '@FORTRAN_MPI_OFFSET@' print(" %s %s" % (T, name), file=Out) print(" PARAMETER (%s=%s)" % (name, G.mpih_defines[name]), file=Out) @@ -1011,7 +1008,10 @@ def dump_mpif_h(f): print(" INTEGER MPI_ERRCODES_IGNORE(1)", file=Out) print(" CHARACTER*1 MPI_ARGVS_NULL(1,1)", file=Out) print(" CHARACTER*1 MPI_ARGV_NULL(1)", file=Out) - print("@DLLIMPORT@", file=Out) + if 'DLLIMPORT' in autoconf_macros: + print(autoconf_macros['DLLIMPORT'], file=Out) + else: + print("@DLLIMPORT@", file=Out) print(" COMMON /MPIFCMB5/ MPI_UNWEIGHTED", file=Out) print(" COMMON /MPIFCMB9/ MPI_WEIGHTS_EMPTY", file=Out) print(" COMMON /MPIFCMBa/ MPI_BUFFER_AUTOMATIC", file=Out) diff --git a/src/binding/abi_fortran/Makefile.am b/src/binding/abi_fortran/Makefile.am index abeeec685a5..218ed8c8a93 100644 --- a/src/binding/abi_fortran/Makefile.am +++ b/src/binding/abi_fortran/Makefile.am @@ -6,8 +6,8 @@ AM_CPPFLAGS = $(MPI_ABI_H_INCLUDE) include_HEADERS = mpi_abi_fort.h -lib_LTLIBRARIES = libmpifort_abi.la modinc_HEADERS = $(mpi_fc_modules) +lib_LTLIBRARIES = libmpifort_abi.la libmpifort_abi_la_SOURCES = libmpifort_abi_la_LDFLAGS = -version-info 1:0:0 @@ -16,13 +16,13 @@ libmpifort_abi_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=FC \ $(AM_FCFLAGS) $(FCFLAGS) $(libmpifort_abi_la_LDFLAGS) \ $(LDFLAGS) -o $@ -convenience_libs = +mpifort_convenience_libs = mpi_abi_lib = -lmpi_abi -# include mpif_h/Makefile.mk +include mpif_h/Makefile.mk # include use_mpi/Makefile.mk # include use_mpi_f08/Makefile.mk -noinst_LTLIBRARIES = $(convenience_libs) +noinst_LTLIBRARIES = $(mpifort_convenience_libs) -libmpifort_abi_la_LIBADD = $(convenience_libs) $(mpi_abi_lib) +libmpifort_abi_la_LIBADD = $(mpifort_convenience_libs) $(mpi_abi_lib) diff --git a/src/binding/abi_fortran/configure.ac b/src/binding/abi_fortran/configure.ac index 1f065791cf9..4a52ef236bd 100644 --- a/src/binding/abi_fortran/configure.ac +++ b/src/binding/abi_fortran/configure.ac @@ -39,10 +39,850 @@ F77=$FC FFLAGS=$FCFLAGS AC_PROG_F77 +# MPI C ABI standard sizes +MPI_STATUS_SIZE=8 +AC_SUBST([MPI_STATUS_SIZE]) + +MPI_SIZEOF_AINT=8 +MPI_SIZEOF_OFFSET=8 +MPI_SIZEOF_COUNT=8 +AC_SUBST([MPI_SIZEOF_AINT]) +AC_SUBST([MPI_SIZEOF_OFFSET]) +AC_SUBST([MPI_SIZEOF_COUNT]) + +# mpi_f08 mapping to C types +get_c_int_type 8 +MPI_AINT=$pac_retval +MPI_OFFSET=$pac_retval +MPI_COUNT=$pac_retval + +enable_f77=yes +enable_f90=yes +enable_f08=yes +PAC_FC_2008_SUPPORT([:],[enable_f08=no]) + modincdir=$includedir AC_SUBST(modincdir) +AC_ARG_ENABLE([two-level-namespace], + [AS_HELP_STRING([--enable-two-level-namespace], + [(Darwin only) Do not use `-Wl,-flat_namespace` to + link libmpifort.dylib. MacOS uses two-level namespace + to compile dylibs by default. This may cause issues + not resolving MPI constants, such as MPI_IN_PLACE. + Thus, we use flat_namespace by default. Enable this + option to use two-level-namespace instead. ])], + [], + [enable_two_level_namespace=no]) +FCLIB_LDFLAGS= +AC_SUBST([FCLIB_LDFLAGS]) + +if test "X$enable_shared" = "Xyes" ; then + # see ticket #1590 for some more background on these Darwin linking issues + AS_CASE([$host], + [*-*-darwin*], + [ + + # The linker on Darwin does not allow common symbols, thus libtool + # adds the -fno-common option by default for shared libraries. + # However, the common symbols defined in different shared libraries + # and object files still can not be treated as the same symbol. + # For example: + # with gfortran, the same common block in the shared libraries and + # the object files will have different memory locations separately; + # with ifort, the same common block in different shared libraries + # will get the same memory location but still get a different location + # in the object file. + + # On the other hand, the -flat-namespace option allows linker to + # unify the same common symbols in different dylibs. It needs to be + # added in linking stage for both the shared library and the final + # executable file. + + # In Fortran programs, we implement global definitions such as MPI_BOTTOM + # as common symbols. We check the address of the user input and translate it + # to the C global definition if it is equal to the internal pre-stored address + # in the Fortran binding layer. Without -flat-namespace, we may get different + # addresses and thus treat the predefined constant as a normal buffer. + + # sanity check that -Wl,-flat_namespace works on darwin, unless the user + # asked us not to add it + if test "X$enable_two_level_namespace" = "Xno"; then + # TODO, move this into a PAC macro with real autoconf caching + pac_cv_wl_flat_namespace_works=no + AC_MSG_CHECKING([if the C compiler accepts -Wl,-flat_namespace]) + PAC_PUSH_FLAG([LDFLAGS]) + PAC_APPEND_FLAG([-Wl,-flat_namespace],[LDFLAGS]) + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[int i;])], + [AC_MSG_RESULT([yes]) + pac_cv_wl_flat_namespace_works=yes], + [AC_MSG_RESULT([no])]) + PAC_POP_FLAG([LDFLAGS]) + + # Technically we may not be able to use the same form of the argument + # for all three compilers (CC/CXX/FC). But we only think this is + # necessary for Darwin for now, so this unconditional, single-var + # approximation will work for now. + if test "X$pac_cv_wl_flat_namespace_works" = "Xyes" ; then + FCLIB_LDFLAGS="-Wl,-flat_namespace" + fi + fi + ] + ) +fi + +# Set NEEDSPLIB to yes if link commands need both -l$MPILIBNAME +# and -lp$MPILIBNAME. +NEEDSPLIB=yes +if test $enable_weak_symbols = yes ; then + # Turn off weak symbols if they aren't available + PAC_PROG_C_WEAK_SYMBOLS(,enable_weak_symbols=no) +fi +if test $enable_weak_symbols = "yes" ; then + AC_DEFINE(USE_WEAK_SYMBOLS,1,[Define if weak symbols should be used]) + NEEDSPLIB=no + # Check for the ability to support multiple weak symbols + if test "$pac_cv_prog_c_weak_symbols" = "pragma weak" ; then + PAC_PROG_C_MULTIPLE_WEAK_SYMBOLS(AC_DEFINE(HAVE_MULTIPLE_PRAGMA_WEAK,1,[Define if multiple weak symbols may be defined])) + fi +fi +AM_CONDITIONAL([BUILD_PROFILING_LIB],[test "$NEEDSPLIB" = "yes"]) + +PAC_CHECK_VISIBILITY +AC_SUBST(VISIBILITY_CFLAGS) +# disable visibility if building profiling library +if test "$NEEDSPLIB" = "yes" ; then + VISIBILITY_CFLAGS="" +fi + +if test "$enable_f77" ; then + PAC_PROG_C_UNALIGNED_DOUBLES(, +[AC_MSG_WARN(Your C compiler $CC does not support unaligned accesses +to doubles. This is required for interoperation with +Fortran (the Fortran standard requires it). +You may need to specify an additional argument to your C compiler to +force it to allow unaligned accesses.)]) +fi + +if test "$enable_f77" = yes ; then + # Check if $MPI_DEFAULT_FOPTS is valid with $F77 + if test -n "$MPI_DEFAULT_FOPTS" ; then + PAC_F77_CHECK_COMPILER_OPTION( [$MPI_DEFAULT_FOPTS], [ + FFLAGS="$FFLAGS $MPI_DEFAULT_FOPTS" + fi +fi + +# +# We need to know the name mangling for Fortran before testing for FC +# compatibility (we need this because of the way we decide to generate +# the Fortran 77 bindings) +if test "$enable_f77" = yes ; then + FLIBS_save="$FLIBS" + FLIBS="" + AC_F77_LIBRARY_LDFLAGS + # The autoconf macro for finding FLIBS sometimes makes mistakes + # (particularly with the Fujitsu frt compiler). This next step + # first sees if the FLIBS is valid with the Fortran compiler + PAC_PROG_F77_FLIBS_VALID + # Now see if FLIBS works with the C compiler + PAC_PROG_F77_CHECK_FLIBS + + # Check F77+FLAGS is compatible with CC+CFLAGS before using F77+CC. + PAC_PROG_F77_OBJ_LINKS_WITH_C + + PAC_PROG_F77_LINKER_WITH_C + # For name mangle, we need the library flags + PAC_PROG_F77_NAME_MANGLE + # Check whether additional libraries are needed when linking with C + PAC_PROG_F77_AND_C_STDIO_LIBS + AC_SUBST(F77_OTHER_LIBS) + + # Warn about mixed name mangling, since many of the tests will fail + if test "$pac_cv_prog_f77_name_mangle" = "mixed" ; then + AC_MSG_WARN([The compiler $F77 uses mixed case names. Fortran is monocase +and many Fortran programs may use either upper or lower case names for MPI +calls. Consider specifying a particular parameter to your Fortran compiler +to select either upper or lower case names. For the Absoft compiler, +-f selects lower case and -N109 selects upper case (if you use -f, also use +-B108 to enable the iargc and getarg routines, which are needed for some +tests and by many user programs). Specify new command +line options by setting the environment variable FFLAGS to include +the options (e.g., setenv FFLAGS "-f -B108"). In addition, make sure that your +Fortran 90 compiler uses a compatible naming choice. For the +Absoft Fortran 90, -YALL_NAMES=LCS selects lower case names and -B108 +adds underscores to names, as required for iargc and getarg. Pass this +information to configure with the FCFLAGS environment variable.]) + # If Fortran implicitly enabled, disable it now. Otherwise, + # abort the configure since warning messages are often lost in + # the output. + AC_MSG_ERROR([Aborting configure because of mixed case names in Fortran. Either select --disable-fortran or set FCFLAGS to force the compiler to select monocase names]) + fi + + # The MPI standard requires that MPI_Init in any language initialize + # MPI in all languages. This can be a problem when objects produced + # by the Fortran compiler require symbols from the Fortran runtime + # (making linking C-only programs unnecessarily difficult). What we test + # here is whether the much more restricted needs of the Fortran + # initialize can be met with no special use of the Fortran runtime + PAC_F77_INIT_WORKS_WITH_C + if test "$pac_f_init_works_with_c" = "yes" ; then + AC_DEFINE(HAVE_MPI_F_INIT_WORKS_WITH_C,1,[Define if the Fortran init code for MPI works from C programs without special libraries]) + fi + + # + # Some Fortran compilers now pass CHARACTER length as a size_t instead + # of as an int. This is hard to test for, since the data is passed by + # value and for characters less than about 2GB long, the correct + # value will be used. In this case, we must use an approach similar to + # the one used by libtool for shared library options - look at the + # compiler name or vendor. + # Known compilers that use size_t instead of int: + # Intel Fortran + # gfortran + # Add others as they become known + AC_ARG_ENABLE(f77characterlen, + AS_HELP_STRING([--enable-f77characterlen], + [Select between int and size_t for the length of a Fortran CHARACTER, depending on the F77 compiler. If --enable-f77characterlen=size_t is given, force the use of size_t. This is used for passing Fortran CHARACTER data between C and Fortran, and is provided for experts. Note that the documentation provided by compiler vendors on the calling convention may not be accurate.]),,enable_f77characterlen=no) + + # Set the default + f77_uses_int_for_str=default + + case "$enable_f77characterlen" in + yes|no) + ;; + size_t) + f77_uses_int_for_str=no + enable_f77characterlen=yes + ;; + int) + f77_uses_int_for_str=yes + enable_f77characterlen=yes + ;; + *) + AC_MSG_ERROR([Invalid value provided for --enable-f77characterlen]) + ;; + esac + + # If we might change the size (enable) and we haven't set the choice, + # attempt to determine it from the compiler name. Risky, but we haven't + # found a reliable way to do this with test codes. + if test "$enable_f77characterlen" = "yes" -a \ + "$f77_uses_int_for_str" = "default" ; then + f77_uses_int_for_str=yes + f77Basename=`basename $F77` + case $f77Basename in + ifort*) + f77_uses_int_for_str=no + ;; + gfortran*) + f77_uses_int_for_str=no + ;; + esac + fi + # This test is disabled for now. Despite information in documentation + # on gfortran, it appears to pass lengths as int, at least in some + # builds (it used movl when tested in 2/2013). Tests that failed + # included infotestf.f, in a call to mpi_info_get. + # Leave this as a place holder until a proper test can be determined. + if test "$enable_f77characterlen" = "yes" -a \ + "$f77_uses_int_for_str" = "no" ; then + AC_DEFINE(USE_FORT_STR_LEN_SIZET,1,[Define if the length of a CHARACTER*(*) string in Fortran should be passed as size_t instead of int] ) + fi +fi + +if test "$enable_f77" = "yes" ; then + # determine shared library flags for F77 + f77_shlib_conf=src/env/f77_shlib.conf + PAC_COMPILER_SHLIB_FLAGS([F77],[$f77_shlib_conf]) + AC_SUBST_FILE([f77_shlib_conf]) + + AC_LANG([Fortran 77]) + PAC_PROG_F77_EXCLAIM_COMMENTS(has_exclaim="yes",has_exclaim="no") + PAC_PROG_F77_HAS_INCDIR(src) + PAC_PROG_F77_LIBRARY_DIR_FLAG + + AC_SUBST(MPIFPMPI) + if test "$MPI_WITH_PMPI" = "no" ; then + # If the PMPI routines are not in the same library with the MPI + # routines, we may need to remove the pmpi declarations + PAC_PROG_F77_ALLOWS_UNUSED_EXTERNALS([MPIFPMPI=",PMPI_WTIME,PMPI_WTICK"],[ + MPIFPMPI=""; + AC_MSG_WARN([Removed PMPI_WTIME and PMPI_WTICK from mpif.h])]) + else + MPIFPMPI=",PMPI_WTIME,PMPI_WTICK" + fi + + # Once we have name mangle, we can try to limit the number of needed libs + dnl F77_IN_C_LIBS is not needed currently because mpirinitf_() in setbotf.f + dnl is called in initthread.c only when FLIBS is not needed to initialize + dnl Fortran constants from a C main, See PAC_F77_INIT_WORKS_WITH_C. + dnl PAC_PROG_F77_IN_C_LIBS + dnl AC_SUBST(F77_IN_C_LIBS) + + # Most systems allow the Fortran compiler to process .F and .F90 files + # using the C preprocessor. However, some systems either do not + # allow this or have serious bugs (OSF Fortran compilers have a bug + # that generates an error message from cpp). The following test + # checks to see if .F works, and if not, whether "cpp -P -C" can be used + # This is needed for Mac OSX 10.5 + PAC_F77_WORKS_WITH_CPP([F77CPP]) + AC_SUBST(F77CPP) + + # Check that the Fortran compiler will allow us to pass arguments + # of different types (e.g., for MPI_Send) + PAC_PROG_F77_MISMATCHED_ARGS(addarg,yes) + if test "X$addarg" != "X" ; then + # Code using mpif.h interface will likely need this flag to compile. + # Code with `use mpi` or `use mpi_f08` do not need this flag. + # Add the flag to mpif77 wrappers. + WRAPPER_EXTRA_F77_FLAGS="$addarg" + fi + AC_SUBST(WRAPPER_EXTRA_F77_FLAGS) +fi + +if test "$enable_f90" = "yes" -o "$enable_f08" = "yes"; then + # determine shared library flags for FC + fc_shlib_conf=src/env/fc_shlib.conf + PAC_COMPILER_SHLIB_FLAGS([FC],[$fc_shlib_conf]) + AC_SUBST_FILE([fc_shlib_conf]) + + # Determine characteristics of the Fortran 90 compiler + # Find a Fortran 90 compiler. Sets FC + # Work around bug in autoconf that adds -g to FCFLAGS + saveFCFLAGS="$FCFLAGS" + dnl FIXME XXX DJG this needs to be reconciled with our separate use of + dnl AC_PROG_FC earlier + dnl PAC_PROG_FC + PAC_PROG_FC_WORKS + FCFLAGS=$saveFCFLAGS + if test "$pac_cv_prog_fc_works" = no ; then + # Reject this compiler + if test "$FC" != "no" ; then + fc_rejected=yes + oldFC="$FC" + FC="no" + fi + fi + + if test "$FC" = "no" ; then + if test "$fc_rejected" = "yes" ; then + AC_MSG_ERROR([Could not find a usable Fortran 90 compiler. The compiler $oldFC may be incompatible with the Fortran 77 compiler $F77; check the output of configure and consult the installation manuals]) + else + AC_MSG_ERROR([Could not find a usable Fortran 90 compiler.]) + fi + fi + + # Find the extension that this compiler uses for modules. + # Sets FCMODEXT (and adds it to the list substed) + # Sets FCMODINCFLAG (and adds it to the list substed) + PAC_FC_MODULE + AC_SUBST(FCMODINCSPEC) + if test -z "$FCMODOUTFLAG" ; then + AC_MSG_ERROR([FCMODOUTFLAG could not be determined but is critical for the current Fortran build system]) + fi + + if test "$pac_cv_fc_module_case" = "upper" ; then + MPIMODNAME=MPI + MPICONSTMODNAME=MPI_CONSTANTS + MPISIZEOFMODNAME=MPI_SIZEOFS + MPIBASEMODNAME=MPI_BASE + PMPIBASEMODNAME=PMPI_BASE + MPI_F08_NAME=MPI_F08 + MPI_F08_LINK_CONSTANTS_NAME=MPI_F08_LINK_CONSTANTS + MPI_F08_CALLBACKS_NAME=MPI_F08_CALLBACKS + MPI_F08_TYPES_NAME=MPI_F08_TYPES + MPI_F08_COMPILE_CONSTANTS_NAME=MPI_F08_COMPILE_CONSTANTS + PMPI_F08_NAME=PMPI_F08 + MPI_C_INTERFACE_NAME=MPI_C_INTERFACE + MPI_C_INTERFACE_NOBUF_NAME=MPI_C_INTERFACE_NOBUF + MPI_C_INTERFACE_GLUE_NAME=MPI_C_INTERFACE_GLUE + MPI_C_INTERFACE_TYPES_NAME=MPI_C_INTERFACE_TYPES + MPI_C_INTERFACE_CDESC_NAME=MPI_C_INTERFACE_CDESC + else + MPIMODNAME=mpi + MPICONSTMODNAME=mpi_constants + MPISIZEOFMODNAME=mpi_sizeofs + MPIBASEMODNAME=mpi_base + PMPIBASEMODNAME=pmpi_base + MPI_F08_NAME=mpi_f08 + MPI_F08_LINK_CONSTANTS_NAME=mpi_f08_link_constants + MPI_F08_CALLBACKS_NAME=mpi_f08_callbacks + MPI_F08_TYPES_NAME=mpi_f08_types + MPI_F08_COMPILE_CONSTANTS_NAME=mpi_f08_compile_constants + PMPI_F08_NAME=pmpi_f08 + MPI_C_INTERFACE_NAME=mpi_c_interface + MPI_C_INTERFACE_NOBUF_NAME=mpi_c_interface_nobuf + MPI_C_INTERFACE_GLUE_NAME=mpi_c_interface_glue + MPI_C_INTERFACE_TYPES_NAME=mpi_c_interface_types + MPI_C_INTERFACE_CDESC_NAME=mpi_c_interface_cdesc + fi + AC_SUBST(MPIMODNAME) + AC_SUBST(MPICONSTMODNAME) + AC_SUBST(MPISIZEOFMODNAME) + AC_SUBST(MPIBASEMODNAME) + AC_SUBST(PMPIBASEMODNAME) + + AC_SUBST(MPI_F08_NAME) + AC_SUBST(MPI_F08_LINK_CONSTANTS_NAME) + AC_SUBST(MPI_F08_CALLBACKS_NAME) + AC_SUBST(MPI_F08_TYPES_NAME) + AC_SUBST(MPI_F08_COMPILE_CONSTANTS_NAME) + AC_SUBST(PMPI_F08_NAME) + AC_SUBST(MPI_C_INTERFACE_NAME) + AC_SUBST(MPI_C_INTERFACE_NOBUF_NAME) + AC_SUBST(MPI_C_INTERFACE_GLUE_NAME) + AC_SUBST(MPI_C_INTERFACE_TYPES_NAME) + AC_SUBST(MPI_C_INTERFACE_CDESC_NAME) + + # Assume that all Fortran 90 compilers accept -I for include directories + FCINC=-I + AC_SUBST(FCINC) + FCINCFLAG=-I + AC_SUBST(FCINCFLAG) + + # Check if $MPI_DEFAULT_FCOPTS is valid with $F90 + if test -n "$MPI_DEFAULT_FCOPTS" ; then + if test "$enable_check_compiler_flags" = "yes" ; then + PAC_FC_CHECK_COMPILER_OPTION( [$MPI_DEFAULT_FCOPTS], [ + FCFLAGS="$FCFLAGS $MPI_DEFAULT_FCOPTS" + ] ) + else + FCFLAGS="$FCFLAGS $MPI_DEFAULT_FCOPTS" + fi + fi + + # Most systems allow the Fortran compiler to process .F and .F90 files + # using the C preprocessor. However, some systems either do not + # allow this or have serious bugs (OSF Fortran compilers have a bug + # that generates an error message from cpp). The following test + # checks to see if .F works, and if not, whether "cpp -P -C" can be used + PAC_FC_WORKS_WITH_CPP([FCCPP]) + AC_SUBST(FCCPP) + + # Check whether additional libraries are needed when linking with C + PAC_PROG_FC_AND_C_STDIO_LIBS + AC_SUBST(FC_OTHER_LIBS) +fi + +PAC_C_MULTI_ATTR_ALIAS +if test "$pac_c_multi_attr_alias" = "yes" ; then + PAC_F2C_ATTR_ALIGNED_SIZE([1],[CMB_1INT_ALIGNMENT]) + AC_SUBST(CMB_1INT_ALIGNMENT) + PAC_F2C_ATTR_ALIGNED_SIZE([$MPI_STATUS_SIZE],[CMB_STATUS_ALIGNMENT],[32]) + AC_SUBST(CMB_STATUS_ALIGNMENT) + if test "X$CMB_1INT_ALIGNMENT" != "X" -a "X$CMB_STATUS_ALIGNMENT" != "X" ; then + AC_DEFINE(HAVE_C_MULTI_ATTR_ALIAS, 1, [Define if multiple __attribute__((alias)) are supported]) + fi +fi + +if test "$enable_f77" = yes ; then + pac_cv_f77_sizeof_character=1 + + # Up to size checking code in main configure.ac (where it tries to + # find the matching C sizes) as part of defining mpi_integer8 etc. + # The results are available in pac_cv_sizeof_f77_ + # Size is 0 if unknown or unavailable (or cross-compiling) + # Due to limitations in autoconf, we cannot put these into a loop. + # We also check integer to find the type of MPI_Fint + # + # Cross-compilation results can be included with the --with-cross=file + # option. + CROSS_F77_SIZEOF_INTEGER=${CROSS_F77_SIZEOF_INTEGER:-0} + CROSS_F77_SIZEOF_REAL=${CROSS_F77_SIZEOF_REAL:-0} + CROSS_F77_SIZEOF_DOUBLE_PRECISION=${CROSS_F77_SIZEOF_DOUBLE_PRECISION:-0} + CROSS_F77_SIZEOF_LOGICAL=${CROSS_F77_SIZEOF_LOGICAL:-0} + PAC_PROG_F77_CHECK_SIZEOF_EXT(integer,$CROSS_F77_SIZEOF_INTEGER) + PAC_PROG_F77_CHECK_SIZEOF_EXT(real,$CROSS_F77_SIZEOF_REAL) + PAC_PROG_F77_CHECK_SIZEOF_EXT(double precision,$CROSS_F77_SIZEOF_DOUBLE_PRECISION) + PAC_PROG_F77_CHECK_SIZEOF_EXT(logical,$CROSS_F77_SIZEOF_LOGICAL) + AC_LANG([Fortran 77]) + # If we have sizes for real and double, we do not need to call + # mpir_get_fsize at run time. + # For the size-defined types (e.g., integer*2), we assume that if the + # compiler allows it, it has the stated size. + AC_CACHE_CHECK([whether integer*1 is supported],pac_cv_fort_integer1,[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ integer*1 i])], + pac_cv_fort_integer1=yes, + pac_cv_fort_integer1=no)]) + AC_CACHE_CHECK([whether integer*2 is supported],pac_cv_fort_integer2,[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ integer*2 i])], + pac_cv_fort_integer2=yes, + pac_cv_fort_integer2=no)]) + AC_CACHE_CHECK([whether integer*4 is supported],pac_cv_fort_integer4,[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ integer*4 i])], + pac_cv_fort_integer4=yes, + pac_cv_fort_integer4=no)]) + AC_CACHE_CHECK([whether integer*8 is supported],pac_cv_fort_integer8,[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ integer*8 i])], + pac_cv_fort_integer8=yes, + pac_cv_fort_integer8=no)]) + AC_CACHE_CHECK([whether integer*16 is supported],pac_cv_fort_integer16,[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ integer*16 i])], + pac_cv_fort_integer16=yes, + pac_cv_fort_integer16=no)]) + AC_CACHE_CHECK([whether real*2 is supported],pac_cv_fort_real2,[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ real*2 a])], + pac_cv_fort_real2=yes, + pac_cv_fort_real2=no)]) + AC_CACHE_CHECK([whether real*4 is supported],pac_cv_fort_real4,[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ real*4 a])], + pac_cv_fort_real4=yes, + pac_cv_fort_real4=no)]) + AC_CACHE_CHECK([whether real*8 is supported],pac_cv_fort_real8,[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ real*8 a])], + pac_cv_fort_real8=yes, + pac_cv_fort_real8=no)]) + AC_CACHE_CHECK([whether real*16 is supported],pac_cv_fort_real16,[ + AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[ real*16 a])], + pac_cv_fort_real16=yes, + pac_cv_fort_real16=no)]) + + if test -z "$pac_cv_f77_sizeof_integer" -o \ + "X$pac_cv_f77_sizeof_integer" = "X0" ; then + AC_MSG_ERROR([Unable to configure with Fortran support because configure could not determine the size of a Fortran INTEGER. Consider setting CROSS_F77_SIZEOF_INTEGER to the length in bytes of a Fortran INTEGER]) + fi + + len_real=`printf "%02x" $pac_cv_f77_sizeof_real` + MPI_REAL=0x4c00${len_real}1c + AC_SUBST(MPI_REAL) + + if test -z "$pac_cv_f77_sizeof_double_precision" ; then + AC_MSG_ERROR([Unable to configure with Fortran support because configure could not determine the size of a Fortran DOUBLE PRECISION. Consider setting CROSS_F77_SIZEOF_DOUBLE_PRECISION to the length in bytes of a Fortran DOUBLE PRECISION]) + fi + + # Provide the corresponding C types for MPI_INTEGER + AC_MSG_CHECKING([for C type matching Fortran integer]) + get_c_int_type $pac_cv_f77_sizeof_integer + MPI_FINT=$pac_retval + AC_MSG_RESULT($MPI_FINT) + + # Provide the corresponding C types for MPI_REAL and MPI_DOUBLE + # These are needed to correctly implement the MPI reduction operations + + AC_MSG_CHECKING([for C type matching Fortran real]) + get_c_float_type $pac_cv_f77_sizeof_real + MPIR_FC_REAL_CTYPE=$pac_retval + AC_MSG_RESULT($MPIR_FC_REAL_CTYPE) + AC_DEFINE_UNQUOTED([MPIR_FC_REAL_CTYPE],[$MPIR_FC_REAL_CTYPE], [The C type for FORTRAN REAL]) + + AC_MSG_CHECKING([for C type matching Fortran double]) + get_c_float_type $pac_cv_f77_sizeof_double_precision + MPIR_FC_DOUBLE_CTYPE=$pac_retval + AC_MSG_RESULT($MPIR_FC_DOUBLE_CTYPE) + AC_DEFINE_UNQUOTED([MPIR_FC_DOUBLE_CTYPE],[$MPIR_FC_DOUBLE_CTYPE], [The C type for FORTRAN DOUBLE PRECISION]) + + # get C types for Fortran fixed-size REAL and INTEGER. If no equivalent C type, set + # pac_cv_f77_sizeof_real# to 0, so that PAC_SET_MPI_TYPE can skip the type. + + PAC_F77_CHECK_FIXED_REAL(4) + PAC_F77_CHECK_FIXED_REAL(8) + PAC_F77_CHECK_FIXED_REAL(16) + + PAC_F77_CHECK_FIXED_INTEGER(1) + PAC_F77_CHECK_FIXED_INTEGER(2) + PAC_F77_CHECK_FIXED_INTEGER(4) + PAC_F77_CHECK_FIXED_INTEGER(8) + PAC_F77_CHECK_FIXED_INTEGER(16) + + # We also need to check the size of MPI_Aint vs MPI_Fint, and + # define AINT_LARGER_THAN_FINT if aint is larger (this + # affects code in MPI_Address) + if test "$ac_cv_sizeof_void_p" != "0" -a \ + "$ac_cv_sizeof_void_p" -gt "$pac_cv_f77_sizeof_integer" ; then + AC_DEFINE(HAVE_AINT_LARGER_THAN_FINT,1,[Define if addresses are larger than Fortran integers]) + fi + if test "$ac_cv_sizeof_void_p" != 0 -a \ + "$ac_cv_sizeof_void_p" != "$pac_cv_f77_sizeof_integer" ; then + AC_DEFINE(HAVE_AINT_DIFFERENT_THAN_FINT,1,[Define if addresses are a different size than Fortran integers]) + fi + + # Include a defined value for Fint is int + if test "$pac_cv_f77_sizeof_integer" == "$ac_cv_sizeof_int" ; then + AC_DEFINE(HAVE_FINT_IS_INT,1,[Define if Fortran integer are the same size as C ints]) + else + AC_MSG_WARN([Fortran integers and C ints are not the same size. Support for this case is experimental; use at your own risk]) + fi + + # Try and compute the values of .true. and .false. in Fortran + # This code has been removed because the Fortran binding code does + # not yet support it. + PAC_F77_LOGICALS_IN_C([$MPI_FINT]) + + # Get the INTEGER_KIND, ADDRESS_KIND and OFFSET_KIND if possible + # + # For Fortran 90, we'll also need MPI_ADDRESS_KIND and MPI_OFFSET_KIND + # Since our compiler might BE a Fortran 90 compiler, try and determine the + # values. + if test "$FC" = "no" ; then + PAC_F77_IS_FC([ + FC=$F77 + if test -z "$FCFLAGS" ; then + FCFLAGS="$FFLAGS" + fi + ]) + fi + if test "$FC" != "no" ; then + # Offset kind should be for 8 bytes if possible (Romio prefers that) + # address should be sizeof void * (unless --with-aint-size has + # been set) + # FIXME in the current configure implementation OFFSET_KIND and + # MPI_Offset won't always agree, but generally will. The MPI Standard + # implies that these types must have identical size, so this is a bug + # waiting to happen. + if test "$with_aint_size" -gt 0 -a \ + "$with_aint_size" -gt "$ac_cv_sizeof_void_p" ; then + testsize=$with_aint_size + else + testsize=$ac_cv_sizeof_void_p + fi + if test "$testsize" = 0 ; then + # Set a default + testsize=4 + fi + dnl Using the {} around testsize helps the comments work correctly + PAC_PROG_FC_INT_KIND(ADDRESS_KIND,${testsize},$CROSS_F90_ADDRESS_KIND) + if test "$testsize" = 8 ; then + OFFSET_KIND=$ADDRESS_KIND + else + PAC_PROG_FC_INT_KIND(OFFSET_KIND,8,$CROSS_F90_OFFSET_KIND) + fi + # + PAC_PROG_FC_INT_KIND(INTEGER_KIND,$pac_cv_f77_sizeof_integer,$CROSS_F90_INTEGER_KIND) + if test "$INTEGER_KIND" = "-1" ; then + # In our experience, this usually means that there is some + # problem building and/or running the f90 program. Fail + # in this case rather than attempt to continue + AC_MSG_ERROR([Unable to determine Fortran 90 KIND values for either address-sized integers or offset-sized integers.]) + fi + # + # Some compilers won't allow a -1 kind (e.g., absoft). In this case, + # use a fallback (sizeof(int) kind) + if test "$ADDRESS_KIND" = "-1" -o "$OFFSET_KIND" = "-1" ; then + if test "$ADDRESS_KIND" = "-1" ; then + ADDRESS_KIND=$INTEGER_KIND + fi + if test "$OFFSET_KIND" = "-1" ; then + OFFSET_KIND=$INTEGER_KIND + fi + fi + AC_LANG_PUSH([Fortran]) + AC_CACHE_CHECK([if real*8 is supported in Fortran 90], + [pac_cv_fort90_real8],[ + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM([],[ real*8 a]) + ],[ + pac_cv_fort90_real8=yes + ],[ + pac_cv_fort90_real8=no + ]) + ]) + AC_LANG_POP([Fortran]) + WTIME_DOUBLE_TYPE="DOUBLE PRECISION" + if test "$pac_cv_fort90_real8" = "yes" ; then + WTIME_DOUBLE_TYPE="REAL*8" + fi + # WTIME_DOUBLE_TYPE is substituted into mpi_base.f90 + AC_SUBST(WTIME_DOUBLE_TYPE) + fi + # Make sure that address kind and offset kind have values. + if test -z "$ADDRESS_KIND" ; then + ADDRESS_KIND=0 + fi + if test -z "$OFFSET_KIND" ; then + OFFSET_KIND=0 + fi + # Note, however, that zero value are (in all practical case) invalid + # for Fortran 90, and indicate a failure. Test and fail if Fortran 90 + # enabled. + if test "$enable_f90" = "yes" ; then + if test "$ADDRESS_KIND" -le 0 -o "$OFFSET_KIND" -le 0 ; then + AC_MSG_ERROR([Unable to determine Fortran 90 integer kinds for MPI types. If you do not need Fortran 90, add --disable-fc to the configure options.]) + fi + fi + AC_SUBST(ADDRESS_KIND) + AC_SUBST(OFFSET_KIND) + AC_SUBST(INTEGER_KIND) + + # Some compilers may require special directives to handle the common + # block in a library. In particular, directives are needed for Microsoft + # Windows to support dynamic library import. The following six + # directives may be needed: + # CMS\$ATTRIBUTES DLLIMPORT::/MPIPRIV1/ + # CMS\$ATTRIBUTES DLLIMPORT::/MPIPRIV2/ + # CMS\$ATTRIBUTES DLLIMPORT::/MPIPRIVC/ + # CDEC\$ATTRIBUTES DLLIMPORT::/MPIPRIV1/ + # CDEC\$ATTRIBUTES DLLIMPORT::/MPIPRIV2/ + # CDEC\$ATTRIBUTES DLLIMPORT::/MPIPRIVC/ + # CMS is for the Microsoft compiler, + # CDEC is (we believe) for the DEC Fortran compiler. + # We need to make this a configure-time variable because some compilers + # (in particular, a version of the Intel Fortran compiler for Linux) + # will read directives for other compilers and then flag as fatal + # errors directives that it does not support but does recognize. + + DLLIMPORT="" + AC_SUBST(DLLIMPORT) + + AC_LANG([C]) +else + MPI_FINT=int + + # set following sizes to 0 will disable the corresponding datatype + pac_cv_f77_sizeof_character=0 + pac_cv_f77_sizeof_integer=0 + pac_cv_f77_sizeof_real=0 + pac_cv_f77_sizeof_double_precision=0 + pac_cv_f77_sizeof_logical=0 + pac_cv_f77_sizeof_integer1=0 + pac_cv_f77_sizeof_integer2=0 + pac_cv_f77_sizeof_integer4=0 + pac_cv_f77_sizeof_integer8=0 + pac_cv_f77_sizeof_integer16=0 + pac_cv_f77_sizeof_real2=0 + pac_cv_f77_sizeof_real4=0 + pac_cv_f77_sizeof_real8=0 + pac_cv_f77_sizeof_real16=0 + + AC_DEFINE(HAVE_NO_FORTRAN_MPI_TYPES_IN_C,1,[Define if the Fortran types are not available in C]) +fi + +if test "$pac_cv_f77_sizeof_integer8" = "0" ; then + FORTRAN_MPI_OFFSET=INTEGER +else + FORTRAN_MPI_OFFSET="INTEGER*8" +fi +export FORTRAN_MPI_OFFSET + +if test "$enable_f90" = "yes"; then + # Determine the precision and range of the standard Fortran types. This + # isn't quite enough for a full implementation of the Type_create_f90_xxx + # routines, but will handle most programs. We can extend this by trying to + # find (through selected_real_kind and selected_int_kind) types with larger or + # smaller precisions and/or ranges than the basic types. + PAC_FC_SIMPLE_NUMBER_MODEL([the precision and range of reals], + [real aa], + [precision(aa), ",", range(aa)], + [FC_REAL_MODEL], + [$CROSS_F90_REAL_MODEL]) + # + PAC_FC_SIMPLE_NUMBER_MODEL([the precision and range of double precision], + [double precision aa], + [precision(aa), ",", range(aa)], + [FC_DOUBLE_MODEL], + [$CROSS_F90_DOUBLE_MODEL]) + # + PAC_FC_SIMPLE_NUMBER_MODEL([the range of integer], + [integer aa], + [range(aa)], + [FC_INTEGER_MODEL], + [$CROSS_F90_INTEGER_MODEL]) + + # Try to find the available integer kinds by using selected_int_kind + # This produces a table of range,kind + PAC_FC_AVAIL_INTEGER_MODELS([FC_ALL_INTEGER_MODELS], + [$CROSS_F90_ALL_INTEGER_MODELS]) + # + PAC_FC_INTEGER_MODEL_MAP([FC_INTEGER_MODEL_MAP], + [$CROSS_F90_INTEGER_MODEL_MAP]) +else + FC_REAL_MODEL="6, 37" + FC_DOUBLE_MODEL="15, 307" + FC_INTEGER_MODEL="4" + FC_INTEGER_MODEL_MAP="{ 9, 4, 4 }," + FC_ALL_INTEGER_MODELS="9, 4," +fi +AC_SUBST(FC_REAL_MODEL) +AC_SUBST(FC_DOUBLE_MODEL) +AC_SUBST(FC_INTEGER_MODEL) +AC_SUBST(FC_ALL_INTEGER_MODELS) +AC_SUBST(FC_INTEGER_MODEL_MAP) + +if test "$enable_f08" = "yes"; then + AS_CASE([$MPI_AINT], + [short], [F08_C_AINT="c_short"], + [int], [F08_C_AINT="c_int"], + [long], [F08_C_AINT="c_long"], + ['long long'], [F08_C_AINT="c_long_long"], + [AC_MSG_ERROR([unable to determine C MPI_AINT type in Fortran 2008])]) + + AS_CASE([$MPI_COUNT], + [short], [F08_C_COUNT="c_short"], + [int], [F08_C_COUNT="c_int"], + [long], [F08_C_COUNT="c_long"], + ['long long'], [F08_C_COUNT="c_long_long"], + [AC_MSG_ERROR([unable to determine C MPI_COUNT type in Fortran 2008])]) + + AS_CASE([$MPI_OFFSET], + [short], [F08_C_OFFSET="c_short"], + [int], [F08_C_OFFSET="c_int"], + [long], [F08_C_OFFSET="c_long"], + ['long long'], [F08_C_OFFSET="c_long_long"], + [AC_MSG_ERROR([unable to determine C MPI_OFFSET type in Fortran 2008])]) + + AC_SUBST(F08_C_AINT) + AC_SUBST(F08_C_COUNT) + AC_SUBST(F08_C_OFFSET) +fi + +AM_CONDITIONAL([BUILD_F77_BINDING],[test "$enable_f77" = "yes"]) +AM_CONDITIONAL([BUILD_F90_BINDING],[test "$enable_f90" = "yes"]) +AM_CONDITIONAL([BUILD_F08_BINDING],[test "$enable_f08" = "yes"]) + +if test "$enable_f90" = "yes" ; then + PAC_FC_CHECK_IGNORE_TKR + PAC_FC_ISO_C_BINDING + if test -z "$PYTHON" ; then + if test -f src/binding/fortran/use_mpi/mpi_base.f90 ; then + AC_MSG_NOTICE([Use pre-generated Fortran mpi binding. To prevent issues, install Python 3 and re-run configure.]) + else + AC_MSG_ERROR([Python 3 is required to generate F90 bindings but not found!]) + fi + else + cmd_f90="$PYTHON $srcdir/maint/gen_binding_f90.py" + # pass in type sizes for MPI_SIZEOF + cmd_f90="$cmd_f90 -f-logical-size=$pac_cv_f77_sizeof_logical" + if test "$pac_fc_ignore_tkr" != "no" ; then + cmd_f90="$cmd_f90 -ignore-tkr=$pac_fc_ignore_tkr" + fi + if test "$pac_fc_iso_c_binding" = "no" ; then + cmd_f90="$cmd_f90 -iso-c-binding=no" + fi + AC_CONFIG_COMMANDS([gen_binding_f90], [$cmd_gen_binding_f90], [cmd_gen_binding_f90="$cmd_f90"]) + fi +fi + +if test "$enable_f08" = "yes" ; then + PAC_FC_CHECK_REAL128 + if test -z "$PYTHON" ; then + if test -f src/binding/fortran/use_mpi_f08/mpi_f08.f90 ; then + AC_MSG_NOTICE([Using pre-generated Fortran mpi_f08 binding source. To prevent issues, install Python 3 and rerun configure.]) + else + AC_MSG_ERROR([Python 3 is required to generate F08 bindings but not found!]) + fi + else + cmd_f08="$PYTHON $srcdir/maint/gen_binding_f08.py" + if test "$pac_fc_has_real128" = "no" ; then + cmd_f08="$cmd_f08 -no-real128" + fi + if test "$enable_romio" = "no" ; then + cmd_f08="$cmd_f08 -no-mpiio" + fi + cmd_f08="$cmd_f08 -fint-size=$pac_cv_f77_sizeof_integer -aint-size=$MPI_SIZEOF_AINT -count-size=$MPI_SIZEOF_COUNT -cint-size=$ac_cv_sizeof_int" + AC_CONFIG_COMMANDS([gen_binding_f08], [$cmd_gen_binding_f08], [cmd_gen_binding_f08="$cmd_f08"]) + fi +fi + AC_CONFIG_FILES([ Makefile ]) + +if test "$enable_f77" = "yes" ; then + AC_CONFIG_FILES([mpif_h/setbotf.f \ + mpif_h/setbot.c]) +fi +if test "$enable_f08" = "yes" ; then + AC_CONFIG_FILES([use_mpi_f08/mpi_f08_compile_constants.f90 \ + use_mpi_f08/mpi_c_interface_types.f90]) +fi + AC_OUTPUT diff --git a/src/binding/abi_fortran/mpif_h/Makefile.mk b/src/binding/abi_fortran/mpif_h/Makefile.mk index a7d02ecb84d..7dbd988505f 100644 --- a/src/binding/abi_fortran/mpif_h/Makefile.mk +++ b/src/binding/abi_fortran/mpif_h/Makefile.mk @@ -3,46 +3,34 @@ ## See COPYRIGHT in top-level directory ## -f77_cppflags = $(AM_CPPFLAGS) -I${main_top_srcdir}/src/binding/fortran/mpif_h +f77_cppflags = $(AM_CPPFLAGS) -Impif_h if BUILD_F77_BINDING -mpifort_convenience_libs += lib/libf77_mpi.la -noinst_LTLIBRARIES += lib/libf77_mpi.la +include_HEADERS += mpif_h/mpif.h -lib_libf77_mpi_la_SOURCES = \ - src/binding/fortran/mpif_h/fortran_binding.c \ - src/binding/fortran/mpif_h/attr_proxy.c \ - src/binding/fortran/mpif_h/fdebug.c \ - src/binding/fortran/mpif_h/setbot.c \ - src/binding/fortran/mpif_h/setbotf.f +mpifort_convenience_libs += libf77_mpi.la -lib_libf77_mpi_la_CPPFLAGS = $(f77_cppflags) +libf77_mpi_la_SOURCES = \ + mpif_h/fortran_binding.c \ + mpif_h/attr_proxy.c \ + mpif_h/fdebug.c \ + mpif_h/setbot.c \ + mpif_h/setbotf.f + +libf77_mpi_la_CPPFLAGS = $(f77_cppflags) if BUILD_PROFILING_LIB -mpifort_convenience_libs += lib/libf77_pmpi.la -noinst_LTLIBRARIES += lib/libf77_pmpi.la +mpifort_convenience_libs += libf77_pmpi.la -lib_libf77_pmpi_la_SOURCES = src/binding/fortran/mpif_h/fortran_binding.c +libf77_pmpi_la_SOURCES = mpif_h/fortran_binding.c # build "pmpi_xxx_" f77 public functions -lib_libf77_pmpi_la_CPPFLAGS = $(f77_cppflags) -DF77_USE_PMPI +libf77_pmpi_la_CPPFLAGS = $(f77_cppflags) -DF77_USE_PMPI # build "mpi_xxx_" f77 public functions -lib_libf77_mpi_la_CPPFLAGS += -DMPICH_MPI_FROM_PMPI -DUSE_ONLY_MPI_NAMES +libf77_mpi_la_CPPFLAGS += -DMPICH_MPI_FROM_PMPI -DUSE_ONLY_MPI_NAMES endif BUILD_PROFILING_LIB -noinst_HEADERS += \ - src/binding/fortran/mpif_h/fortran_profile.h \ - src/binding/fortran/mpif_h/mpi_fortimpl.h - -# config.status copies src/binding/fortran/mpif_h/mpif.h to src/include (see the relevant -# AC_CONFIG_COMMANDS in configure.ac), so we need to delete it at distclean time -# too. More work is needed in this Makefile.mk to keep src/include/mpif.h up to -# date w.r.t. the src/binding/fortran/mpif_h version. -DISTCLEANFILES += src/binding/fortran/mpif_h/mpif.h src/include/mpif.h -nodist_include_HEADERS += src/binding/fortran/mpif_h/mpif.h - - endif BUILD_F77_BINDING From 6d0a5e4c0307cadd3ec18ac2bea52361c403500f Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Wed, 3 Apr 2024 11:52:30 -0500 Subject: [PATCH 7/8] abi_fortran: reimplement attr_proxy.c Re-implement proxy wrappers for attribute callbacks that does not rely on internal backdoor functions to pass the Fortran context. --- src/binding/abi_fortran/mpif_h/attr_proxy.c | 211 ++++++++++++++++-- src/binding/abi_fortran/mpif_h/mpi_fortimpl.h | 15 +- 2 files changed, 206 insertions(+), 20 deletions(-) diff --git a/src/binding/abi_fortran/mpif_h/attr_proxy.c b/src/binding/abi_fortran/mpif_h/attr_proxy.c index 38e42012283..a1a4ebb27a7 100644 --- a/src/binding/abi_fortran/mpif_h/attr_proxy.c +++ b/src/binding/abi_fortran/mpif_h/attr_proxy.c @@ -5,41 +5,216 @@ #include "mpi_fortimpl.h" -static int MPII_copy_attr_f90_proxy(MPI_Comm_copy_attr_function * user_function, int handle, - int keyval, void *extra_state, MPIR_Attr_type value_type, - void *value, void **new_value, int *flag) +/* --------------------- */ +struct F77_attr_state { + int keyval; + F77_CopyFunction *copyfn; + F77_DeleteFunction *delfn; + void *extra_state; +}; + +static int MPII_copy_proxy(MPI_Comm comm, int keyval, void *extra_state, + void *val_in, void *val_out, int *flag) +{ + struct F77_attr_state *p = extra_state; + MPI_Fint ierr = 0; + MPI_Fint fhandle = MPI_Comm_c2f(comm); + MPI_Fint fkeyval = (MPI_Fint) keyval; + MPI_Fint *fextra = (MPI_Fint *) p->extra_state; + MPI_Fint fvalue = (MPI_Fint) (intptr_t) val_in; + MPI_Fint fnew = 0; + MPI_Fint fflag = 0; + + p->copyfn(&fhandle, &fkeyval, &fextra, &fvalue, &fnew, &fflag, &ierr); + + *flag = MPII_FROM_FLOG(fflag); + *(void **) val_out = (void *) (intptr_t) fnew; + return (int) ierr; +} + +static int MPII_del_proxy(MPI_Comm comm, int keyval, void *value, void *extra_state) +{ + struct F77_attr_state *p = extra_state; + MPI_Fint ierr = 0; + MPI_Fint fhandle = MPI_Comm_c2f(comm); + MPI_Fint fkeyval = (MPI_Fint) keyval; + MPI_Fint fvalue = (int) (intptr_t) value; + MPI_Fint *fextra = (MPI_Fint *) p->extra_state; + + p->delfn(&fhandle, &fkeyval, &fvalue, fextra, &ierr); + return (int) ierr; +} + +int MPII_keyval_create(F77_CopyFunction * copyfn, + F77_DeleteFunction * delfn, void *extra_state, int *keyval) +{ + struct F77_attr_state *p = malloc(sizeof(struct F77_attr_state)); + int ret = MPI_Comm_create_keyval(MPII_copy_proxy, + MPII_del_proxy, + &keyval, p); + if (ret == MPI_SUCCESS) { + p->keyval = keyval; + p->copyfn = copyfn; + p->delfn = delfn; + p->extra_state = extra_state; + } + return ret; +} + +/* --------------------- */ +struct F90_attr_state { + int keyval; + F90_CopyFunction *copyfn; + F90_DeleteFunction *delfn; + void *extra_state; +}; + +static int MPII_comm_copy_proxy(MPI_Comm comm, int keyval, void *extra_state, + void *val_in, void *val_out, int *flag) +{ + struct F90_attr_state *p = extra_state; + MPI_Fint ierr = 0; + MPI_Fint fhandle = MPI_Comm_c2f(comm); + MPI_Fint fkeyval = (MPI_Fint) keyval; + MPI_Aint *fextra = (MPI_Aint *) p->extra_state; + MPI_Aint fvalue = (MPI_Aint) (intptr_t) val_in; + MPI_Aint fnew = 0; + MPI_Fint fflag = 0; + + p->copyfn(&fhandle, &fkeyval, &fextra, &fvalue, &fnew, &fflag, &ierr); + + *flag = MPII_FROM_FLOG(fflag); + *(void **) val_out = (void *) (intptr_t) fnew; + return (int) ierr; +} + +static int MPII_comm_del_proxy(MPI_Comm comm, int keyval, void *value, void *extra_state) +{ + struct F90_attr_state *p = extra_state; + MPI_Fint ierr = 0; + MPI_Fint fhandle = MPI_Comm_c2f(comm); + MPI_Fint fkeyval = (MPI_Fint) keyval; + MPI_Aint fvalue = (MPI_Aint) (intptr_t) value; + MPI_Aint *fextra = (MPI_Aint *) p->extra_state; + + p->delfn(&fhandle, &fkeyval, &fvalue, fextra, &ierr); + return (int) ierr; +} + +int MPII_comm_keyval_create(F90_CopyFunction * copyfn, + F90_DeleteFunction * delfn, void *extra_state, int *keyval) +{ + struct F90_attr_state *p = malloc(sizeof(struct F90_attr_state)); + int ret = MPI_Comm_create_keyval(MPII_comm_copy_proxy, + MPII_comm_del_proxy, + &keyval, p); + if (ret == MPI_SUCCESS) { + p->keyval = keyval; + p->copyfn = copyfn; + p->delfn = delfn; + p->extra_state = extra_state; + } else { + free(p); + } + return ret; +} + +static int MPII_type_copy_proxy(MPI_Datatype type, int keyval, void *extra_state, + void *val_in, void *val_out, int *flag) +{ + struct F90_attr_state *p = extra_state; + MPI_Fint ierr = 0; + MPI_Fint fhandle = MPI_Type_c2f(type); + MPI_Fint fkeyval = (MPI_Fint) keyval; + MPI_Aint *fextra = (MPI_Aint *) p->extra_state; + MPI_Aint fvalue = (MPI_Aint) (intptr_t) val_in; + MPI_Aint fnew = 0; + MPI_Fint fflag = 0; + + p->copyfn(&fhandle, &fkeyval, &fextra, &fvalue, &fnew, &fflag, &ierr); + + *flag = MPII_FROM_FLOG(fflag); + *(void **) val_out = (void *) (intptr_t) fnew; + return (int) ierr; +} + +static int MPII_type_del_proxy(MPI_Datatype type, int keyval, void *value, void *extra_state) +{ + struct F90_attr_state *p = extra_state; + MPI_Fint ierr = 0; + MPI_Fint fhandle = MPI_Type_c2f(type); + MPI_Fint fkeyval = (MPI_Fint) keyval; + MPI_Aint fvalue = (MPI_Aint) (intptr_t) value; + MPI_Aint *fextra = (MPI_Aint *) p->extra_state; + + p->delfn(&fhandle, &fkeyval, &fvalue, fextra, &ierr); + return (int) ierr; +} + +int MPII_type_keyval_create(F90_CopyFunction * copyfn, + F90_DeleteFunction * delfn, void *extra_state, int *keyval) +{ + struct F90_attr_state *p = malloc(sizeof(struct F90_attr_state)); + int ret = MPI_Type_create_keyval(MPII_type_copy_proxy, + MPII_type_del_proxy, + &keyval, p); + if (ret == MPI_SUCCESS) { + p->keyval = keyval; + p->copyfn = copyfn; + p->delfn = delfn; + p->extra_state = extra_state; + } else { + free(p); + } + return ret; +} + +static int MPII_win_copy_proxy(MPI_Win win, int keyval, void *extra_state, + void *val_in, void *val_out, int *flag) { + struct F90_attr_state *p = extra_state; MPI_Fint ierr = 0; - MPI_Fint fhandle = (MPI_Fint) handle; + MPI_Fint fhandle = MPI_Win_c2f(win); MPI_Fint fkeyval = (MPI_Fint) keyval; - MPI_Aint fvalue = (MPI_Aint) value; - MPI_Aint *fextra = (MPI_Aint *) extra_state; + MPI_Aint *fextra = (MPI_Aint *) p->extra_state; + MPI_Aint fvalue = (MPI_Aint) (intptr_t) val_in; MPI_Aint fnew = 0; MPI_Fint fflag = 0; - ((F90_CopyFunction *) (void *) user_function) (&fhandle, &fkeyval, fextra, &fvalue, &fnew, - &fflag, &ierr); + p->copyfn(&fhandle, &fkeyval, &fextra, &fvalue, &fnew, &fflag, &ierr); *flag = MPII_FROM_FLOG(fflag); - *new_value = (void *) fnew; + *(void **) val_out = (void *) (intptr_t) fnew; return (int) ierr; } -static int MPII_delete_attr_f90_proxy(MPI_Comm_delete_attr_function * user_function, int handle, - int keyval, MPIR_Attr_type value_type, void *value, - void *extra_state) +static int MPII_win_del_proxy(MPI_Win win, int keyval, void *value, void *extra_state) { + struct F90_attr_state *p = extra_state; MPI_Fint ierr = 0; - MPI_Fint fhandle = (MPI_Fint) handle; + MPI_Fint fhandle = MPI_Win_c2f(win); MPI_Fint fkeyval = (MPI_Fint) keyval; - MPI_Aint fvalue = (MPI_Aint) value; - MPI_Aint *fextra = (MPI_Aint *) extra_state; + MPI_Aint fvalue = (MPI_Aint) (intptr_t) value; + MPI_Aint *fextra = (MPI_Aint *) p->extra_state; - ((F90_DeleteFunction *) (void *) user_function) (&fhandle, &fkeyval, &fvalue, fextra, &ierr); + p->delfn(&fhandle, &fkeyval, &fvalue, fextra, &ierr); return (int) ierr; } -void MPII_Keyval_set_f90_proxy(int keyval) +int MPII_win_keyval_create(F90_CopyFunction * copyfn, + F90_DeleteFunction * delfn, void *extra_state, int *keyval) { - MPII_Keyval_set_proxy(keyval, MPII_copy_attr_f90_proxy, MPII_delete_attr_f90_proxy); + struct F90_attr_state *p = malloc(sizeof(struct F90_attr_state)); + int ret = MPI_Win_create_keyval(MPII_win_copy_proxy, + MPII_win_del_proxy, + &keyval, p); + if (ret == MPI_SUCCESS) { + p->keyval = keyval; + p->copyfn = copyfn; + p->delfn = delfn; + p->extra_state = extra_state; + } else { + free(p); + } + return ret; } diff --git a/src/binding/abi_fortran/mpif_h/mpi_fortimpl.h b/src/binding/abi_fortran/mpif_h/mpi_fortimpl.h index bad20364178..1aef9bfea9d 100644 --- a/src/binding/abi_fortran/mpif_h/mpi_fortimpl.h +++ b/src/binding/abi_fortran/mpif_h/mpi_fortimpl.h @@ -375,13 +375,24 @@ typedef char *MPID_FCHAR_T; #endif #endif /* HAVE_ROMIO */ -/* The F90 attr copy/delete function prototype and calling convention */ +/* The F77/F90 attr copy/delete function prototype and calling convention */ +typedef void (FORT_CALL F77_CopyFunction) (MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, + MPI_Fint *, MPI_Fint *, MPI_Fint *); +typedef void (FORT_CALL F77_DeleteFunction) (MPI_Fint *, MPI_Fint *, MPI_Fint *, MPI_Fint *, + MPI_Fint *); typedef void (FORT_CALL F90_CopyFunction) (MPI_Fint *, MPI_Fint *, MPI_Aint *, MPI_Aint *, MPI_Aint *, MPI_Fint *, MPI_Fint *); typedef void (FORT_CALL F90_DeleteFunction) (MPI_Fint *, MPI_Fint *, MPI_Aint *, MPI_Aint *, MPI_Fint *); -void MPII_Keyval_set_f90_proxy(int keyval); +int MPII_keyval_create(F77_CopyFunction * copyfn, F77_DeleteFunction * delfn, + void *extra_state, int *keyval); +int MPII_comm_keyval_create(F90_CopyFunction * copyfn, F90_DeleteFunction * delfn, + void *extra_state, int *keyval); +int MPII_type_keyval_create(F90_CopyFunction * copyfn, F90_DeleteFunction * delfn, + void *extra_state, int *keyval); +int MPII_win_keyval_create(F90_CopyFunction * copyfn, F90_DeleteFunction * delfn, + void *extra_state, int *keyval); extern FORT_DLL_SPEC void FORT_CALL mpi_alloc_mem_cptr_(MPI_Aint * size, MPI_Fint * info, void **baseptr, MPI_Fint * ierr); From e2e673ae5c7ebbd1099a7f0786f534ff263216ca Mon Sep 17 00:00:00 2001 From: Hui Zhou Date: Tue, 2 Apr 2024 14:28:13 -0500 Subject: [PATCH 8/8] abi_fortran: build mpif_h --- maint/gen_binding_abi_fortran.py | 33 +++- maint/local_python/binding_f77.py | 38 ++-- src/binding/abi_fortran/configure.ac | 35 ++-- src/binding/abi_fortran/mpif_h/Makefile.mk | 1 - src/binding/abi_fortran/mpif_h/fdebug.c | 178 ------------------ src/binding/abi_fortran/mpif_h/mpi_fortimpl.h | 11 +- 6 files changed, 69 insertions(+), 227 deletions(-) delete mode 100644 src/binding/abi_fortran/mpif_h/fdebug.c diff --git a/maint/gen_binding_abi_fortran.py b/maint/gen_binding_abi_fortran.py index 66738794550..31e10b67965 100644 --- a/maint/gen_binding_abi_fortran.py +++ b/maint/gen_binding_abi_fortran.py @@ -7,6 +7,7 @@ from local_python.mpi_api import * from local_python.binding_common import * from local_python.binding_f77 import * +from local_python.binding_f08 import * from local_python import RE import os @@ -16,16 +17,13 @@ def main(): binding_dir = G.get_srcdir_path("src/binding") f77_dir = "src/binding/abi_fortran/mpif_h" + f08_dir = "src/binding/abi_fortran/use_mpi_f08" - func_list = load_C_func_list(binding_dir, True) # suppress noise - - func_list.extend(get_mpiio_func_list()) - func_list.extend(get_f77_dummy_func_list()) - func_list.append(G.FUNCS['mpi_f_sync_reg']) + func_list = load_C_func_list(binding_dir, True, custom_dir=None) # suppress noise # preprocess for func in func_list: - check_func_directives(func) + check_func_directives_abi(func) func_list = [f for f in func_list if '_skip_fortran' not in f] # fortran_binding.c @@ -39,9 +37,9 @@ def has_cptr(func): G.profile_out = [] for func in func_list: G.out.append("") - dump_f77_c_func(func) + dump_f77_c_func(func, is_abi=True) if has_cptr(func): - dump_f77_c_func(func, True) + dump_f77_c_func(func, True, is_abi=True) f = "%s/fortran_binding.c" % f77_dir dump_f77_c_file(f, G.out) @@ -75,6 +73,9 @@ def has_cptr(func): f = "%s/mpif.h" % f77_dir dump_mpif_h(f, autoconf_macros) + f = "%s/mpi_f08_compile_constants.f90" % f08_dir + dump_compile_constants_f90(f) + def load_mpi_abi_h(f): # load constants into G.mpih_defines with open(f, "r") as In: @@ -84,9 +85,9 @@ def load_mpi_abi_h(f): if RE.match(r'#define\s+(MPI_\w+)\s+(.+)', line): # direct macros (name, val) = RE.m.group(1, 2) - if RE.match(r'\(+MPI_\w+\)\(?0x([0-9a-fA-F]+)', val): + if RE.match(r'\(+(MPI_\w+)\)\(?0x([0-9a-fA-F]+)', val): # handle constants - val = int(RE.m.group(1), 16) + val = "%s(%d)" % (RE.m.group(1), int(RE.m.group(2), 16)) elif RE.match(r'\(+MPI_Offset\)(-?\d+)', val): # MPI_DISPLACEMENT_CURRENT val = RE.m.group(1) @@ -112,6 +113,18 @@ def load_mpi_abi_h(f): (name, val) = RE.m.group(1, 2) G.mpih_defines[name] = val +def check_func_directives_abi(func): + if RE.match(r'mpi_t_', func['name'], re.IGNORECASE): + func['_skip_fortran'] = 1 + elif RE.match(r'mpix_(grequest_|type_iov)', func['name'], re.IGNORECASE): + func['_skip_fortran'] = 1 + elif RE.match(r'mpi_\w+_(f|f08|c)2(f|f08|c)$', func['name'], re.IGNORECASE): + # implemented in mpi_f08_types.f90 + func['_skip_fortran'] = 1 + elif RE.match(r'mpi_.*_function$', func['name'], re.IGNORECASE): + # defined in mpi_f08_callbacks.f90 + func['_skip_fortran'] = 1 + # --------------------------------------------------------- if __name__ == "__main__": main() diff --git a/maint/local_python/binding_f77.py b/maint/local_python/binding_f77.py index 69b58624e0d..9e044b839bd 100644 --- a/maint/local_python/binding_f77.py +++ b/maint/local_python/binding_f77.py @@ -9,7 +9,7 @@ import re -def dump_f77_c_func(func, is_cptr=False): +def dump_f77_c_func(func, is_cptr=False, is_abi=False): func_name = get_function_name(func) f_mapping = get_kind_map('F90') c_mapping = get_kind_map('C') @@ -68,15 +68,23 @@ def dump_p(p): raise Exception("Unhandled: %s - %s, length=%s" % (func['name'], p['name'], p['length'])) else: c_param_list.append("MPI_Fint *" + p['name']) - c_arg_list_A.append("(%s) (*%s)" % (c_type, p['name'])) - c_arg_list_B.append("(%s) (*%s)" % (c_type, p['name'])) + if is_abi and c_type in G.handle_list: + arg = "%s_f2c(*%s)" % (c_type, p['name']) + else: + arg = "(%s) (*%s)" % (c_type, p['name']) + c_arg_list_A.append(arg) + c_arg_list_B.append(arg) def dump_scalar_out(v, f_type, c_type): c_param_list.append("%s *%s" % (f_type, v)) c_arg_list_A.append("&%s_i" % v) c_arg_list_B.append("&%s_i" % v) code_list_common.append("%s %s_i;" % (c_type, v)) - end_list_common.append("*%s = (%s) %s_i;" % (v, f_type, v)) + if is_abi and c_type in G.handle_list: + val = "%s_c2f(%s_i)" % (c_type, v) + else: + val = "(%s) %s_i" % (f_type, v) + end_list_common.append("*%s = %s;" % (v, val)) # void * def dump_buf(buf, check_in_place): @@ -498,7 +506,7 @@ def dump_attr_out(v, c_type, flag): end_list_common.append("if (*ierr || !%s) {" % flag) end_list_common.append(" *%s = 0;" % v) end_list_common.append("} else {") - end_list_common.append(" *%s = (MPI_Aint) %s_i;" % (v, v)) + end_list_common.append(" *%s = (%s) (intptr_t) (*(void **) %s_i);" % (v, c_type, v)) end_list_common.append("}") def dump_handle_create(v, c_type): @@ -845,19 +853,7 @@ def process_func_parameters(): process_func_parameters() c_func_name = func_name - if need_ATTR_AINT: - if RE.match(r'MPI_Attr_(get|put)', func['name'], re.IGNORECASE): - if RE.m.group(1) == 'put': - c_func_name = "MPII_Comm_set_attr" - else: - c_func_name = "MPII_Comm_get_attr" - c_arg_list_A.append("MPIR_ATTR_INT") - c_arg_list_B.append("MPIR_ATTR_INT") - else: - c_func_name = re.sub(r'MPI_', 'MPII_', func['name']) - c_arg_list_A.append("MPIR_ATTR_AINT") - c_arg_list_B.append("MPIR_ATTR_AINT") - elif re.match(r'MPI_(Init|Init_thread|Info_create_env)$', func['name'], re.IGNORECASE): + if re.match(r'MPI_(Init|Init_thread|Info_create_env)$', func['name'], re.IGNORECASE): # argc, argv c_arg_list_A.insert(0, "0, 0") c_arg_list_B.insert(0, "0, 0") @@ -961,6 +957,7 @@ def dump_mpif_h(f, autoconf_macros={}): # -- all integer constants for name in G.mpih_defines: + val = G.mpih_defines[name] T = "INTEGER" if re.match(r'MPI_[TF]_', name): continue @@ -975,8 +972,11 @@ def dump_mpif_h(f, autoconf_macros={}): T = autoconf_macros['FORTRAN_MPI_OFFSET'] else: T = '@FORTRAN_MPI_OFFSET@' + elif isinstance(val, str) and RE.match(r'(MPI_\w+)\((.+)\)', val): + # handles in F77 are just ITNEGERs + val = RE.m.group(2) print(" %s %s" % (T, name), file=Out) - print(" PARAMETER (%s=%s)" % (name, G.mpih_defines[name]), file=Out) + print(" PARAMETER (%s=%s)" % (name, val), file=Out) # -- Fortran08 capability for a in ['SUBARRAYS_SUPPORTED', 'ASYNC_PROTECTS_NONBLOCKING']: diff --git a/src/binding/abi_fortran/configure.ac b/src/binding/abi_fortran/configure.ac index 4a52ef236bd..53c22835b72 100644 --- a/src/binding/abi_fortran/configure.ac +++ b/src/binding/abi_fortran/configure.ac @@ -39,6 +39,9 @@ F77=$FC FFLAGS=$FCFLAGS AC_PROG_F77 +AC_DEFINE([MPI_ABI], 1, [Define to use MPI ABI header.]) +AC_DEFINE([MPI_ABI_FORT], 1, [Define to include MPI ABI Fortran header.]) + # MPI C ABI standard sizes MPI_STATUS_SIZE=8 AC_SUBST([MPI_STATUS_SIZE]) @@ -57,8 +60,8 @@ MPI_OFFSET=$pac_retval MPI_COUNT=$pac_retval enable_f77=yes -enable_f90=yes -enable_f08=yes +enable_f90=no +enable_f08=no PAC_FC_2008_SUPPORT([:],[enable_f08=no]) modincdir=$includedir @@ -168,7 +171,8 @@ if test "$enable_f77" = yes ; then # Check if $MPI_DEFAULT_FOPTS is valid with $F77 if test -n "$MPI_DEFAULT_FOPTS" ; then PAC_F77_CHECK_COMPILER_OPTION( [$MPI_DEFAULT_FOPTS], [ - FFLAGS="$FFLAGS $MPI_DEFAULT_FOPTS" + FFLAGS="$FFLAGS $MPI_DEFAULT_FOPTS" + ]) fi fi @@ -291,11 +295,6 @@ information to configure with the FCFLAGS environment variable.]) fi if test "$enable_f77" = "yes" ; then - # determine shared library flags for F77 - f77_shlib_conf=src/env/f77_shlib.conf - PAC_COMPILER_SHLIB_FLAGS([F77],[$f77_shlib_conf]) - AC_SUBST_FILE([f77_shlib_conf]) - AC_LANG([Fortran 77]) PAC_PROG_F77_EXCLAIM_COMMENTS(has_exclaim="yes",has_exclaim="no") PAC_PROG_F77_HAS_INCDIR(src) @@ -342,7 +341,7 @@ fi if test "$enable_f90" = "yes" -o "$enable_f08" = "yes"; then # determine shared library flags for FC - fc_shlib_conf=src/env/fc_shlib.conf + fc_shlib_conf=confdb/fc_shlib.conf PAC_COMPILER_SHLIB_FLAGS([FC],[$fc_shlib_conf]) AC_SUBST_FILE([fc_shlib_conf]) @@ -828,11 +827,14 @@ AM_CONDITIONAL([BUILD_F77_BINDING],[test "$enable_f77" = "yes"]) AM_CONDITIONAL([BUILD_F90_BINDING],[test "$enable_f90" = "yes"]) AM_CONDITIONAL([BUILD_F08_BINDING],[test "$enable_f08" = "yes"]) +# Python 3 is needed to generate Fortran bindings +PAC_CHECK_PYTHON + if test "$enable_f90" = "yes" ; then PAC_FC_CHECK_IGNORE_TKR PAC_FC_ISO_C_BINDING if test -z "$PYTHON" ; then - if test -f src/binding/fortran/use_mpi/mpi_base.f90 ; then + if test -f use_mpi/mpi_base.f90 ; then AC_MSG_NOTICE([Use pre-generated Fortran mpi binding. To prevent issues, install Python 3 and re-run configure.]) else AC_MSG_ERROR([Python 3 is required to generate F90 bindings but not found!]) @@ -854,7 +856,7 @@ fi if test "$enable_f08" = "yes" ; then PAC_FC_CHECK_REAL128 if test -z "$PYTHON" ; then - if test -f src/binding/fortran/use_mpi_f08/mpi_f08.f90 ; then + if test -f use_mpi_f08/mpi_f08.f90 ; then AC_MSG_NOTICE([Using pre-generated Fortran mpi_f08 binding source. To prevent issues, install Python 3 and rerun configure.]) else AC_MSG_ERROR([Python 3 is required to generate F08 bindings but not found!]) @@ -877,12 +879,15 @@ AC_CONFIG_FILES([ ]) if test "$enable_f77" = "yes" ; then - AC_CONFIG_FILES([mpif_h/setbotf.f \ - mpif_h/setbot.c]) + AC_CONFIG_FILES([ + mpif_h/setbotf.f + mpif_h/setbot.c + ]) fi if test "$enable_f08" = "yes" ; then - AC_CONFIG_FILES([use_mpi_f08/mpi_f08_compile_constants.f90 \ - use_mpi_f08/mpi_c_interface_types.f90]) + AC_CONFIG_FILES([ + use_mpi_f08/mpi_c_interface_types.f90 + ]) fi AC_OUTPUT diff --git a/src/binding/abi_fortran/mpif_h/Makefile.mk b/src/binding/abi_fortran/mpif_h/Makefile.mk index 7dbd988505f..807aac3ffc4 100644 --- a/src/binding/abi_fortran/mpif_h/Makefile.mk +++ b/src/binding/abi_fortran/mpif_h/Makefile.mk @@ -14,7 +14,6 @@ mpifort_convenience_libs += libf77_mpi.la libf77_mpi_la_SOURCES = \ mpif_h/fortran_binding.c \ mpif_h/attr_proxy.c \ - mpif_h/fdebug.c \ mpif_h/setbot.c \ mpif_h/setbotf.f diff --git a/src/binding/abi_fortran/mpif_h/fdebug.c b/src/binding/abi_fortran/mpif_h/fdebug.c deleted file mode 100644 index 57078c39592..00000000000 --- a/src/binding/abi_fortran/mpif_h/fdebug.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) by Argonne National Laboratory - * See COPYRIGHT in top-level directory - */ - -/* style: allow:fprintf:21 sig:0 */ - -#include "mpi_fortimpl.h" - -#if defined(HAVE_PRAGMA_WEAK) && defined(HAVE_MULTIPLE_PRAGMA_WEAK) -void mpir_is_bottom_(void *a, int *ierr); -void mpir_is_in_place_(void *a, int *ierr); -/* FIXME probably MPI_WEIGHTS_EMPTY needs support somewhere in this file */ -void mpir_is_unweighted_(void *a, int *ierr); -void mpir_is_status_ignore_(void *a, int *ierr); -void mpir_is_statuses_ignore_(void *a, int *ierr); -void mpir_is_errcodes_ignore_(void *a, int *ierr); -void mpir_is_argvs_null_(void *a, int *ierr); - -extern void MPIR_IS_BOTTOM(void *a, int *ierr); -extern void mpir_is_bottom(void *a, int *ierr); -extern void mpir_is_bottom__(void *a, int *ierr); -extern void MPIR_IS_IN_PLACE(void *a, int *ierr); -extern void mpir_is_in_place(void *a, int *ierr); -extern void mpir_is_in_place__(void *a, int *ierr); -extern void MPIR_IS_UNWEIGHTED(void *a, int *ierr); -extern void mpir_is_unweighted(void *a, int *ierr); -extern void mpir_is_unweighted__(void *a, int *ierr); -extern void MPIR_IS_STATUS_IGNORE(void *a, int *ierr); -extern void mpir_is_status_ignore(void *a, int *ierr); -extern void mpir_is_status_ignore__(void *a, int *ierr); -extern void MPIR_IS_STATUSES_IGNORE(void *a, int *ierr); -extern void mpir_is_statuses_ignore(void *a, int *ierr); -extern void mpir_is_statuses_ignore__(void *a, int *ierr); -extern void MPIR_IS_ERRCODES_IGNORE(void *a, int *ierr); -extern void mpir_is_errcodes_ignore(void *a, int *ierr); -extern void mpir_is_errcodes_ignore__(void *a, int *ierr); -extern void MPIR_IS_ARGVS_NULL(void *a, int *ierr); -extern void mpir_is_argvs_null(void *a, int *ierr); -extern void mpir_is_argvs_null__(void *a, int *ierr); - -#pragma weak MPIR_IS_BOTTOM = mpir_is_bottom_ -#pragma weak mpir_is_bottom = mpir_is_bottom_ -#pragma weak mpir_is_bottom__ = mpir_is_bottom_ -#pragma weak MPIR_IS_IN_PLACE = mpir_is_in_place_ -#pragma weak mpir_is_in_place = mpir_is_in_place_ -#pragma weak mpir_is_in_place__ = mpir_is_in_place_ -#pragma weak MPIR_IS_UNWEIGHTED = mpir_is_unweighted_ -#pragma weak mpir_is_unweighted = mpir_is_unweighted_ -#pragma weak mpir_is_unweighted__ = mpir_is_unweighted_ -#pragma weak MPIR_IS_STATUS_IGNORE = mpir_is_status_ignore_ -#pragma weak mpir_is_status_ignore = mpir_is_status_ignore_ -#pragma weak mpir_is_status_ignore__ = mpir_is_status_ignore_ -#pragma weak MPIR_IS_STATUSES_IGNORE = mpir_is_statuses_ignore_ -#pragma weak mpir_is_statuses_ignore = mpir_is_statuses_ignore_ -#pragma weak mpir_is_statuses_ignore__ = mpir_is_statuses_ignore_ -#pragma weak MPIR_IS_ERRCODES_IGNORE = mpir_is_errcodes_ignore_ -#pragma weak mpir_is_errcodes_ignore = mpir_is_errcodes_ignore_ -#pragma weak mpir_is_errcodes_ignore__ = mpir_is_errcodes_ignore_ -#pragma weak MPIR_IS_ARGVS_NULL = mpir_is_argvs_null_ -#pragma weak mpir_is_argvs_null = mpir_is_argvs_null_ -#pragma weak mpir_is_argvs_null__ = mpir_is_argvs_null_ -#else -#if defined(F77_NAME_UPPER) -#define mpir_is_bottom_ MPIR_IS_BOTTOM -#define mpir_is_in_place_ MPIR_IS_IN_PLACE -#define mpir_is_unweighted_ MPIR_IS_UNWEIGHTED -#define mpir_is_status_ignore_ MPIR_IS_STATUS_IGNORE -#define mpir_is_statuses_ignore_ MPIR_IS_STATUSES_IGNORE -#define mpir_is_errcodes_ignore_ MPIR_IS_ERRCODES_IGNORE -#define mpir_is_argvs_null_ MPIR_IS_ARGVS_NULL -#elif defined(F77_NAME_LOWER_2USCORE) -#define mpir_is_bottom_ mpir_is_bottom__ -#define mpir_is_in_place_ mpir_is_in_place__ -#define mpir_is_unweighted_ mpir_is_unweighted__ -#define mpir_is_status_ignore_ mpir_is_status_ignore__ -#define mpir_is_statuses_ignore_ mpir_is_statuses_ignore__ -#define mpir_is_errcodes_ignore_ mpir_is_errcodes_ignore__ -#define mpir_is_argvs_null_ mpir_is_argvs_null__ -#elif defined(F77_NAME_LOWER) -#define mpir_is_bottom_ mpir_is_bottom -#define mpir_is_in_place_ mpir_is_in_place -#define mpir_is_unweighted_ mpir_is_unweighted -#define mpir_is_status_ignore_ mpir_is_status_ignore -#define mpir_is_statuses_ignore_ mpir_is_statuses_ignore -#define mpir_is_errcodes_ignore_ mpir_is_errcodes_ignore -#define mpir_is_argvs_null_ mpir_is_argvs_null -#endif - -void mpir_is_bottom_(void *a, int *ierr); -void mpir_is_in_place_(void *a, int *ierr); -void mpir_is_unweighted_(void *a, int *ierr); -void mpir_is_status_ignore_(void *a, int *ierr); -void mpir_is_statuses_ignore_(void *a, int *ierr); -void mpir_is_errcodes_ignore_(void *a, int *ierr); -void mpir_is_argvs_null_(void *a, int *ierr); - -#endif - -#include - -/* --BEGIN DEBUG-- */ -/* - Define Fortran functions MPIR_IS_() that are callable in Fortran - to check if the Fortran constants, MPI_, are recognized by the MPI - implementation (in C library). -*/ -void mpir_is_bottom_(void *a, int *ierr) -{ - *ierr = (a == MPIR_F_MPI_BOTTOM ? 1 : 0); - if (*ierr) - fprintf(stderr, "Matched : "); - else - fprintf(stderr, "Not matched : "); - fprintf(stderr, "MPIR_F_MPI_BOTTOM=%p, MPI_BOTTOM=%p\n", MPIR_F_MPI_BOTTOM, a); -} - -void mpir_is_in_place_(void *a, int *ierr) -{ - *ierr = (a == MPIR_F_MPI_IN_PLACE ? 1 : 0); - if (*ierr) - fprintf(stderr, "Matched : "); - else - fprintf(stderr, "Not matched : "); - fprintf(stderr, "MPIR_F_MPI_IN_PLACE=%p, MPI_IN_PLACE=%p\n", MPIR_F_MPI_IN_PLACE, a); -} - -void mpir_is_unweighted_(void *a, int *ierr) -{ - *ierr = (a == MPIR_F_MPI_UNWEIGHTED ? 1 : 0); - if (*ierr) - fprintf(stderr, "Matched : "); - else - fprintf(stderr, "Not matched : "); - fprintf(stderr, "MPIR_F_MPI_UNWEIGHTED=%p, MPI_UNWEIGHTED=%p\n", MPIR_F_MPI_UNWEIGHTED, a); -} - -void mpir_is_status_ignore_(void *a, int *ierr) -{ - *ierr = (a == MPI_F_STATUS_IGNORE ? 1 : 0); - if (*ierr) - fprintf(stderr, "Matched : "); - else - fprintf(stderr, "Not matched : "); - fprintf(stderr, "MPI_F_STATUS_IGNORE=%p, MPI_STATUS_IGNORE=%p\n", MPI_F_STATUS_IGNORE, a); -} - -void mpir_is_statuses_ignore_(void *a, int *ierr) -{ - *ierr = (a == MPI_F_STATUSES_IGNORE ? 1 : 0); - if (*ierr) - fprintf(stderr, "Matched : "); - else - fprintf(stderr, "Not matched : "); - fprintf(stderr, "MPI_F_STATUSES_IGNORE=%p, MPI_STATUSES_IGNORE=%p\n", MPI_F_STATUSES_IGNORE, a); -} - -void mpir_is_errcodes_ignore_(void *a, int *ierr) -{ - *ierr = (a == MPI_F_ERRCODES_IGNORE ? 1 : 0); - if (*ierr) - fprintf(stderr, "Matched : "); - else - fprintf(stderr, "Not matched : "); - fprintf(stderr, "MPI_F_ERRCODES_IGNORE=%p, MPI_ERRCODES_IGNORE=%p\n", MPI_F_ERRCODES_IGNORE, a); -} - -void mpir_is_argvs_null_(void *a, int *ierr) -{ - *ierr = (a == MPI_F_ARGVS_NULL ? 1 : 0); - if (*ierr) - fprintf(stderr, "Matched : "); - else - fprintf(stderr, "Not matched : "); - fprintf(stderr, "MPI_F_ARGVS_NULL=%p, MPI_ARGVS_NULL=%p\n", MPI_F_ARGVS_NULL, a); -} - -/* --END DEBUG-- */ diff --git a/src/binding/abi_fortran/mpif_h/mpi_fortimpl.h b/src/binding/abi_fortran/mpif_h/mpi_fortimpl.h index 1aef9bfea9d..0f6d8b48eb5 100644 --- a/src/binding/abi_fortran/mpif_h/mpi_fortimpl.h +++ b/src/binding/abi_fortran/mpif_h/mpi_fortimpl.h @@ -6,15 +6,15 @@ #ifndef MPI_FORTIMPL_H_INCLUDED #define MPI_FORTIMPL_H_INCLUDED -#include "mpichconf.h" +#include "config.h" #include "mpi.h" -#include "mpir_attr_generic.h" -#include "mpii_f77interface.h" #include /* for ssize_t */ #include #include #include +#define MPICH_API_PUBLIC + /* Handle different mechanisms for passing Fortran CHARACTER to routines. * * In the case where MPI_Fint is a different size from int, it appears that @@ -280,7 +280,10 @@ typedef MPI_Aint MPI_FAint; /* The definitions for the Fortran logical values are also needed by the reduction operations in mpi/coll/opland, oplor, and oplxor, so they are defined in src/include/mpii_fortlogical.h */ -#include "mpii_fortlogical.h" +#define MPII_F_TRUE 1 +#define MPII_F_FALSE 0 +#define MPII_TO_FLOG(a) ((a) ? MPII_F_TRUE : MPII_F_FALSE) +#define MPII_FROM_FLOG(a) ((a) == MPII_F_FALSE ? 0 : 1) /* MPIR_F_MPI_BOTTOM is the address of the Fortran MPI_BOTTOM value */