Skip to content

Commit

Permalink
abi_fortran: build mpif_h
Browse files Browse the repository at this point in the history
  • Loading branch information
hzhou committed Apr 3, 2024
1 parent 6d0a5e4 commit e2e673a
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 227 deletions.
33 changes: 23 additions & 10 deletions maint/gen_binding_abi_fortran.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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:
Expand All @@ -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)
Expand All @@ -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()
Expand Down
38 changes: 19 additions & 19 deletions maint/local_python/binding_f77.py
Original file line number Diff line number Diff line change
Expand Up @@ -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')
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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")
Expand Down Expand Up @@ -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
Expand All @@ -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']:
Expand Down
35 changes: 20 additions & 15 deletions src/binding/abi_fortran/configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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])
Expand All @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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])

Expand Down Expand Up @@ -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!])
Expand All @@ -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!])
Expand All @@ -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
1 change: 0 additions & 1 deletion src/binding/abi_fortran/mpif_h/Makefile.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading

0 comments on commit e2e673a

Please sign in to comment.