Skip to content

Commit

Permalink
Generate mpi_f08 bindings and add CFI support
Browse files Browse the repository at this point in the history
This updates fortran/use-mpi-f08 to generate most of the Fortran
bindings from a script and template files. It also adds support for
Fortran TS 29113 when possible, allowing for better Fortran array
handling that matches the standard.

The C files were imported from PR #10302 and converted to templates to
be fed into the binding script.

Co-authored-by: Gilles Gouaillardet <gilles@rist.or.jp>
Co-authored-by: Howard Pritchard <howardp@lanl.gov>
Signed-off-by: Jake Tronge <jtronge@lanl.gov>
  • Loading branch information
3 people committed Oct 29, 2024
1 parent b2413cf commit 1926928
Show file tree
Hide file tree
Showing 355 changed files with 12,033 additions and 8,316 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ ompi/mpi/fortran/mpiext/mpi-ext-module.F90
ompi/mpi/fortran/mpiext/mpi-f08-ext-module.F90
ompi/mpi/fortran/mpiext-use-mpi/mpi-ext-module.F90
ompi/mpi/fortran/mpiext-use-mpi-f08/mpi-f08-ext-module.F90
ompi/mpi/fortran/use-mpi-f08/psizeof_f08.f90

ompi/mpi/fortran/mpif-h/sizeof_f.f90
ompi/mpi/fortran/mpif-h/profile/p*.c
Expand Down
1 change: 0 additions & 1 deletion config/ompi_config_files.m4
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ AC_DEFUN([OMPI_CONFIG_FILES],[
ompi/mpi/fortran/use-mpi-ignore-tkr/mpi-ignore-tkr-file-interfaces.h
ompi/mpi/fortran/use-mpi-ignore-tkr/mpi-ignore-tkr-removed-interfaces.h
ompi/mpi/fortran/use-mpi-f08/Makefile
ompi/mpi/fortran/use-mpi-f08/profile/Makefile
ompi/mpi/fortran/use-mpi-f08/base/Makefile
ompi/mpi/fortran/use-mpi-f08/bindings/Makefile
ompi/mpi/fortran/use-mpi-f08/mod/Makefile
Expand Down
3 changes: 2 additions & 1 deletion ompi/mpi/bindings/ompi_bindings/fortran.py
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,9 @@ def print_c_source_header(out):
out.dump('#include "ompi/file/file.h"')
out.dump('#include "ompi/errhandler/errhandler.h"')
out.dump('#include "ompi/datatype/ompi_datatype.h"')
out.dump('#include "ompi/mca/coll/base/coll_base_util.h"')
out.dump('#include "ts.h"')
out.dump('#include "array.h"')
out.dump('#include "bigcount.h"')


def print_binding(prototype, lang, out, bigcount=False, template=None):
Expand Down
290 changes: 288 additions & 2 deletions ompi/mpi/bindings/ompi_bindings/fortran_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,17 @@ def c_parameter(self):
return f'OMPI_CFI_BUFFER *{self.name}'


@FortranType.add('C_PTR_OUT')
class CptrType(FortranType):
def declare(self):
return f'TYPE(C_PTR), INTENT(OUT) :: {self.name}'

def use(self):
return [('ISO_C_BINDING', 'C_PTR')]

def c_parameter(self):
return f'char *{self.name}'

@FortranType.add('COUNT')
class CountType(FortranType):
def declare(self):
Expand All @@ -191,6 +202,50 @@ def c_parameter(self):
type_ = 'MPI_Count' if self.bigcount else 'MPI_Fint'
return f'{type_} *{self.name}'

@FortranType.add('COUNT_INOUT')
class CountTypeInOut(FortranType):
"""COUNT type with INOUT INTENT"""
def declare(self):
if self.bigcount:
return f'INTEGER(KIND=MPI_COUNT_KIND), INTENT(INOUT) :: {self.name}'
else:
return f'INTEGER, INTENT(INOUT) :: {self.name}'

def use(self):
return [('mpi_f08_types', 'MPI_COUNT_KIND')]

def c_parameter(self):
type_ = 'MPI_Count' if self.bigcount else 'MPI_Fint'
return f'{type_} *{self.name}'

@FortranType.add('COUNT_OUT')
class CountTypeInOut(FortranType):
"""COUNT type with OUT INTENT"""
def declare(self):
if self.bigcount:
return f'INTEGER(KIND=MPI_COUNT_KIND), INTENT(OUT) :: {self.name}'
else:
return f'INTEGER, INTENT(IN) :: {self.name}'

def use(self):
return [('mpi_f08_types', 'MPI_COUNT_KIND')]

def c_parameter(self):
type_ = 'MPI_Count' if self.bigcount else 'MPI_Fint'
return f'{type_} *{self.name}'


@FortranType.add('PARTITIONED_COUNT')
class PartitionedCountType(FortranType):
def declare(self):
return f'INTEGER(KIND=MPI_COUNT_KIND), INTENT(IN) :: {self.name}'

def use(self):
return [('mpi_f08_types', 'MPI_COUNT_KIND')]

def c_parameter(self):
return f'MPI_Count *{self.name}'


@FortranType.add('DATATYPE')
class DatatypeType(FortranType):
Expand All @@ -209,6 +264,24 @@ def use(self):
def c_parameter(self):
return f'MPI_Fint *{self.name}'

@FortranType.add('DATATYPE_OUT')
class DatatypeTypeOut(FortranType):
def declare(self):
return f'TYPE(MPI_Datatype), INTENT(OUT) :: {self.name}'

def declare_cbinding_fortran(self):
return f'INTEGER, INTENT(OUT) :: {self.name}'

def argument(self):
return f'{self.name}%MPI_VAL'

def use(self):
return [('mpi_f08_types', 'MPI_Datatype')]

def c_parameter(self):
return f'MPI_Fint *{self.name}'



@FortranType.add('DATATYPE_ARRAY')
class DatatypeArrayType(FortranType):
Expand Down Expand Up @@ -293,8 +366,20 @@ def c_parameter(self):
return f'MPI_Fint *{self.name}'


@FortranType.add('STATUS_OUT')
@FortranType.add('STATUS')
class StatusType(FortranType):
def declare(self):
return f'TYPE(MPI_Status) :: {self.name}'

def use(self):
return [('mpi_f08_types', 'MPI_Status')]

def c_parameter(self):
return f'MPI_Fint *{self.name}'


@FortranType.add('STATUS_OUT')
class StatusOutType(FortranType):
def declare(self):
return f'TYPE(MPI_Status), INTENT(OUT) :: {self.name}'

Expand Down Expand Up @@ -382,9 +467,28 @@ def c_parameter(self):
count_type = 'MPI_Count' if self.bigcount else 'MPI_Fint'
return f'{count_type} *{self.name}'

@FortranType.add('AINT_COUNT_ARRAY')
class CountArray(IntArray):
"""Array of MPI_Count or int."""

def declare(self):
kind = '(KIND=MPI_COUNT_KIND)' if self.bigcount else '(KIND=MPI_ADDRESS_KIND)'
return f'INTEGER{kind}, INTENT(IN) :: {self.name}(*)'

def use(self):
if self.bigcount:
return [('mpi_f08_types', 'MPI_COUNT_KIND')]
else:
return [('mpi_f08_types', 'MPI_ADDRESS_KIND')]

def c_parameter(self):
count_type = 'MPI_Count' if self.bigcount else 'MPI_Aint'
return f'{count_type} *{self.name}'



@FortranType.add('AINT')
class Disp(FortranType):
class Aint(FortranType):
"""MPI_Aint type."""

def declare(self):
Expand All @@ -397,6 +501,95 @@ def c_parameter(self):
return f'MPI_Aint *{self.name}'


@FortranType.add('AINT_OUT')
class AintOut(FortranType):
"""MPI_Aint out type."""

def declare(self):
return f'INTEGER(MPI_ADDRESS_KIND), INTENT(OUT) :: {self.name}'

def use(self):
return [('mpi_f08_types', 'MPI_ADDRESS_KIND')]

def c_parameter(self):
return f'MPI_Aint *{self.name}'


@FortranType.add('AINT_COUNT')
class AintCountTypeIn(FortranType):
"""AINT/COUNT type with ININTENT"""
def declare(self):
if self.bigcount:
return f'INTEGER(KIND=MPI_COUNT_KIND), INTENT(IN) :: {self.name}'
else:
return f'INTEGER(KIND=MPI_ADDRESS_KIND), INTENT(IN) :: {self.name}'

def use(self):
if self.bigcount:
return [('mpi_f08_types', 'MPI_COUNT_KIND')]
else:
return [('mpi_f08_types', 'MPI_ADDRESS_KIND')]

def c_parameter(self):
type_ = 'MPI_Count' if self.bigcount else 'MPI_Aint'
return f'{type_} *{self.name}'


@FortranType.add('AINT_COUNT_INOUT')
class AintCountTypeInOut(FortranType):
"""AINT/COUNT type with INOUT INTENT"""
def declare(self):
if self.bigcount:
return f'INTEGER(KIND=MPI_COUNT_KIND), INTENT(INOUT) :: {self.name}'
else:
return f'INTEGER(KIND=MPI_ADDRESS_KIND), INTENT(INOUT) :: {self.name}'

def use(self):
if self.bigcount:
return [('mpi_f08_types', 'MPI_COUNT_KIND')]
else:
return [('mpi_f08_types', 'MPI_ADDRESS_KIND')]

def c_parameter(self):
type_ = 'MPI_Count' if self.bigcount else 'MPI_Aint'
return f'{type_} *{self.name}'


@FortranType.add('AINT_COUNT_OUT')
class AintCountTypeOut(FortranType):
"""AINT/COUNT type with OUT INTENT"""
def declare(self):
if self.bigcount:
return f'INTEGER(KIND=MPI_COUNT_KIND), INTENT(OUT) :: {self.name}'
else:
return f'INTEGER(KIND=MPI_ADDRESS_KIND), INTENT(OUT) :: {self.name}'

def use(self):
if self.bigcount:
return [('mpi_f08_types', 'MPI_COUNT_KIND')]
else:
return [('mpi_f08_types', 'MPI_ADDRESS_KIND')]

def c_parameter(self):
type_ = 'MPI_Count' if self.bigcount else 'MPI_Aint'
return f'{type_} *{self.name}'


@FortranType.add('AINT_ARRAY')
class AintArrayType(FortranType):
"""Array of MPI_Aint."""

def declare(self):
# TODO: Should there be a separate ASYNC version here, when the OMPI_ASYNCHRONOUS attr is required?
return f'INTEGER(KIND=MPI_ADDRESS_KIND), INTENT(IN) OMPI_ASYNCHRONOUS :: {self.name}(*)'

def use(self):
return [('mpi_f08_types', 'MPI_ADDRESS_KIND')]

def c_parameter(self):
return f'MPI_Aint *{self.name}'


@FortranType.add('DISP')
class Disp(FortranType):
"""Displacecment type."""
Expand All @@ -414,6 +607,23 @@ def c_parameter(self):
count_type = 'MPI_Aint' if self.bigcount else 'MPI_Fint'
return f'{count_type} *{self.name}'

@FortranType.add('DISP_OUT')
class DispOut(FortranType):
"""Displacecment out type."""

def declare(self):
kind = '(KIND=MPI_ADDRESS_KIND)' if self.bigcount else ''
return f'INTEGER{kind}, INTENT(OUT) :: {self.name}'

def use(self):
if self.bigcount:
return [('mpi_f08_types', 'MPI_ADDRESS_KIND')]
return []

def c_parameter(self):
count_type = 'MPI_Aint' if self.bigcount else 'MPI_Fint'
return f'{count_type} *{self.name}'


@FortranType.add('DISP_ARRAY')
class DispArray(IntArray):
Expand Down Expand Up @@ -460,6 +670,25 @@ def use(self):
def c_parameter(self):
return f'MPI_Fint *{self.name}'

@FortranType.add('WIN_OUT')
class WinOut(FortranType):
"""MPI_Win out type."""

def declare(self):
return f'TYPE(MPI_Win), INTENT(OUT) :: {self.name}'

def declare_cbinding_fortran(self):
return f'INTEGER, INTENT(OUT) :: {self.name}'

def argument(self):
return f'{self.name}%MPI_VAL'

def use(self):
return [('mpi_f08_types', 'MPI_Win')]

def c_parameter(self):
return f'MPI_Fint *{self.name}'


@FortranType.add('FILE')
class File(FortranType):
Expand All @@ -473,3 +702,60 @@ def use(self):

def c_parameter(self):
return f'MPI_Fint *{self.name}'

@FortranType.add('INFO')
class Info(FortranType):
"""MPI_Info type."""

def declare(self):
return f'TYPE(MPI_Info), INTENT(IN) :: {self.name}'

def use(self):
return [('mpi_f08_types', 'MPI_Info')]

def c_parameter(self):
return f'MPI_Fint *{self.name}'

@FortranType.add('OFFSET')
class Offset(FortranType):
"""MPI_Offset type."""

def declare(self):
return f'INTEGER(MPI_OFFSET_KIND), INTENT(IN) :: {self.name}'

def use(self):
return [('mpi_f08_types', 'MPI_OFFSET_KIND')]

def c_parameter(self):
return f'MPI_Offset *{self.name}'


@FortranType.add('CHAR_ARRAY')
class CharArray(FortranType):
"""Fortran CHAR type."""

def declare(self):
return f'CHARACTER(LEN=*), INTENT(IN) :: {self.name}'

def use(self):
return [('iso_c_binding', 'c_char')]

def declare_cbinding_fortran(self):
return f'CHARACTER(KIND=C_CHAR), INTENT(IN) :: {self.name}(*)'

def c_parameter(self):
return f'char *{self.name}'


@FortranType.add('MESSAGE_INOUT')
class MessageInOut(FortranType):
"""MPI_Message INOUT type."""

def declare(self):
return f'TYPE(MPI_Message), INTENT(INOUT) :: {self.name}'

def use(self):
return [('mpi_f08_types', 'MPI_Message')]

def c_parameter(self):
return f'MPI_Fint *{self.name}'
2 changes: 1 addition & 1 deletion ompi/mpi/bindings/ompi_bindings/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def load(fname, prefix=None, type_constructor=None):
header.append(line)

if not prototype:
raise RuntimeError('missing prototype')
raise RuntimeError(f'missing prototype for {fname}')
# Parse the prototype
prototype = ''.join(prototype)
prototype = prototype[len('PROTOTYPE'):]
Expand Down
Loading

0 comments on commit 1926928

Please sign in to comment.