1
1
openmpi/ompi/mpi/f77/constants.h
Jeff Squyres 0c102e6e5b Fix OSX linker problems with the Fortran bindings:
- ensure to initialize the values that we use for fortran constants
  (even tough their *values* don't matter -- only their *addresses* do,
  but initializing them or not has implications for the OSX linker)
- move the fortran constants to a file with functions in it, because
  the OSX linker sometimes does not import global variables from
  object files that do not have functions (I'm not even going to
  pretend to get all the subtle details about the OSX linker right
  here -- it's just "better" to have global variables in object files
  with functions that otherwise get pulled in during linker
  resolution).

This commit was SVN r10908.
2006-07-20 19:48:03 +00:00

220 строки
9.2 KiB
C

/*
* Copyright (c) 2004-2005 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2004-2005 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
* reserved.
* Copyright (c) 2004-2005 High Performance Computing Center Stuttgart,
* University of Stuttgart. All rights reserved.
* Copyright (c) 2004-2005 The Regents of the University of California.
* All rights reserved.
* Copyright (c) 2006 Cisco Systems, Inc. All rights reserved.
* $COPYRIGHT$
*
* Additional copyrights may follow
*
* $HEADER$
*/
#ifndef OMPI_F77_CONSTANTS_H
#define OMPI_F77_CONSTANTS_H
/*
* Several variables are used to link against MPI F77 constants which
* correspond to addresses, e.g. MPI_BOTTOM, and are implemented via
* common blocks. They must have the same size and alignment
* constraints as the corresponding F77 common blocks.
*
* We use common blocks so that in the C wrapper functions, we can
* compare the address that comes in against known addresses (e.g., if
* the "status" argument in MPI_RECV is the address of the common
* block for the fortran equivalent of MPI_STATUS_IGNORE, then we know
* to pass the C MPI_STATUS_IGNORE to the C MPI_Recv function.
*
* This mojo makes a type that will be aligned on 16 bytes (same as
* common blocks -- at least it seems to work with all the fortran
* compilers that we care about... haven't found one yet that doesn't
* work...)
*/
#if defined(HAVE_LONG_DOUBLE) && OMPI_ALIGNMENT_LONG_DOUBLE == 16
typedef struct { long double bogus[1]; } ompi_fortran_common_t;
#define OMPI_FORTRAN_COMMON_INIT {{ 0 }}
#else
typedef struct { double bogus[2]; } ompi_fortran_common_t;
#define OMPI_FORTRAN_COMMON_INIT {{ 0, 0 }}
#endif
/*
* This part sucks. :-(
*
* Since we made the fundamental decision to support all 4 common
* fortran compiler symbol conventions within the same library for
* those compilers who support weak symbols, we need to have 4 symbols
* for each of the fortran address constants. As described above, we
* have to have known *pointer* values for the fortran addresses
* (e.g., MPI_STATUS_IGNORE). So when the fortran wrapper for
* MPI_RECV gets (MPI_Fint *status), it can check (status ==
* some_sentinel_value) to know that it got the Fortran equivalent of
* MPI_STATUS_IGNORE and therefore pass the C MPI_STATUS_IGNORE to the
* C MPI_Recv.
*
* We do this by having a "common" block in mpif.h:
*
* DOUBLE PRECISION MPI_STATUS_IGNORE
* common /mpi_fortran_status_ignore/ MPI_STATUS_IGNORE
*
* This makes the fortran variable MPI_STATUS_IGNORE effectively be an
* alias for the C variable "mpi_fortran_status_ignore" -- but the C
* symbol name is according to the fortran compiler's naming symbol
* convention bais. So it could be MPI_FORTRAN_STATUS_IGNORE,
* mpi_fortran_status_ignore, mpi_fortran_status_ignore_, or
* mpi_fortran_status_ignore__.
*
* Hence, we have to have *4* C symbols for this, and them compare for
* all of them in the fortran MPI_RECV wrapper. :-( I can't think of
* any better way to do this.
*
* I'm putting these 4 comparisons in macros (on systems where we
* don't support the 4 symbols -- e.g., OSX, where we don't have weak
* symbols -- it'll only be one comparison), so if anyone things of
* something better than this, you should only need to modify this
* file.
*/
#define DECL(upper_case, lower_case, single_u, double_u) \
OMPI_DECLSPEC extern ompi_fortran_common_t upper_case; \
OMPI_DECLSPEC extern ompi_fortran_common_t lower_case; \
OMPI_DECLSPEC extern ompi_fortran_common_t single_u; \
OMPI_DECLSPEC extern ompi_fortran_common_t double_u
DECL(MPI_FORTRAN_BOTTOM, mpi_fortran_bottom,
mpi_fortran_bottom_, mpi_fortran_bottom__);
DECL(MPI_FORTRAN_IN_PLACE, mpi_fortran_in_place,
mpi_fortran_in_place_, mpi_fortran_in_place__);
DECL(MPI_FORTRAN_ARGV_NULL, mpi_fortran_argv_null,
mpi_fortran_argv_null_, mpi_fortran_argv_null__);
DECL(MPI_FORTRAN_ARGVS_NULL, mpi_fortran_argvs_null,
mpi_fortran_argvs_null_, mpi_fortran_argvs_null__);
DECL(MPI_FORTRAN_ERRCODES_IGNORE, mpi_fortran_errcodes_ignore,
mpi_fortran_errcodes_ignore_, mpi_fortran_errcodes_ignore__);
DECL(MPI_FORTRAN_STATUS_IGNORE, mpi_fortran_status_ignore,
mpi_fortran_status_ignore_, mpi_fortran_status_ignore__);
DECL(MPI_FORTRAN_STATUSES_IGNORE, mpi_fortran_statuses_ignore,
mpi_fortran_statuses_ignore_, mpi_fortran_statuses_ignore__);
/*
* Create macros to do the checking. Only check for all 4 if we have
* weak symbols. Otherwise, just check for the one relevant symbol.
*/
#if OMPI_HAVE_WEAK_SYMBOLS
#define OMPI_IS_FORTRAN_BOTTOM(addr) \
(addr == (void*) &MPI_FORTRAN_BOTTOM || \
addr == (void*) &mpi_fortran_bottom || \
addr == (void*) &mpi_fortran_bottom_ || \
addr == (void*) &mpi_fortran_bottom__)
#define OMPI_IS_FORTRAN_IN_PLACE(addr) \
(addr == (void*) &MPI_FORTRAN_IN_PLACE || \
addr == (void*) &mpi_fortran_in_place || \
addr == (void*) &mpi_fortran_in_place_ || \
addr == (void*) &mpi_fortran_in_place__)
#define OMPI_IS_FORTRAN_ARGV_NULL(addr) \
(addr == (void*) &MPI_FORTRAN_ARGV_NULL || \
addr == (void*) &mpi_fortran_argv_null || \
addr == (void*) &mpi_fortran_argv_null_ || \
addr == (void*) &mpi_fortran_argv_null__)
#define OMPI_IS_FORTRAN_ARGVS_NULL(addr) \
(addr == (void*) &MPI_FORTRAN_ARGVS_NULL || \
addr == (void*) &mpi_fortran_argvs_null || \
addr == (void*) &mpi_fortran_argvs_null_ || \
addr == (void*) &mpi_fortran_argvs_null__)
#define OMPI_IS_FORTRAN_ERRCODES_IGNORE(addr) \
(addr == (void*) &MPI_FORTRAN_ERRCODES_IGNORE || \
addr == (void*) &mpi_fortran_errcodes_ignore || \
addr == (void*) &mpi_fortran_errcodes_ignore_ || \
addr == (void*) &mpi_fortran_errcodes_ignore__)
#define OMPI_IS_FORTRAN_STATUS_IGNORE(addr) \
(addr == (void*) &MPI_FORTRAN_STATUS_IGNORE || \
addr == (void*) &mpi_fortran_status_ignore || \
addr == (void*) &mpi_fortran_status_ignore_ || \
addr == (void*) &mpi_fortran_status_ignore__)
#define OMPI_IS_FORTRAN_STATUSES_IGNORE(addr) \
(addr == (void*) &MPI_FORTRAN_STATUSES_IGNORE || \
addr == (void*) &mpi_fortran_statuses_ignore || \
addr == (void*) &mpi_fortran_statuses_ignore_ || \
addr == (void*) &mpi_fortran_statuses_ignore__)
#elif OMPI_F77_CAPS
#define OMPI_IS_FORTRAN_BOTTOM(addr) \
(addr == (void*) &MPI_FORTRAN_BOTTOM)
#define OMPI_IS_FORTRAN_IN_PLACE(addr) \
(addr == (void*) &MPI_FORTRAN_IN_PLACE)
#define OMPI_IS_FORTRAN_ARGV_NULL(addr) \
(addr == (void*) &MPI_FORTRAN_ARGV_NULL)
#define OMPI_IS_FORTRAN_ARGVS_NULL(addr) \
(addr == (void*) &MPI_FORTRAN_ARGVS_NULL)
#define OMPI_IS_FORTRAN_ERRCODES_IGNORE(addr) \
(addr == (void*) &MPI_FORTRAN_ERRCODES_IGNORE)
#define OMPI_IS_FORTRAN_STATUS_IGNORE(addr) \
(addr == (void*) &MPI_FORTRAN_STATUS_IGNORE)
#define OMPI_IS_FORTRAN_STATUSES_IGNORE(addr) \
(addr == (void*) &MPI_FORTRAN_STATUSES_IGNORE)
#elif OMPI_F77_PLAIN
#define OMPI_IS_FORTRAN_BOTTOM(addr) \
(addr == (void*) &mpi_fortran_bottom)
#define OMPI_IS_FORTRAN_IN_PLACE(addr) \
(addr == (void*) &mpi_fortran_in_place)
#define OMPI_IS_FORTRAN_ARGV_NULL(addr) \
(addr == (void*) &mpi_fortran_argv_null)
#define OMPI_IS_FORTRAN_ARGVS_NULL(addr) \
(addr == (void*) &mpi_fortran_argvs_null)
#define OMPI_IS_FORTRAN_ERRCODES_IGNORE(addr) \
(addr == (void*) &mpi_fortran_errcodes_ignore)
#define OMPI_IS_FORTRAN_STATUS_IGNORE(addr) \
(addr == (void*) &mpi_fortran_status_ignore)
#define OMPI_IS_FORTRAN_STATUSES_IGNORE(addr) \
(addr == (void*) &mpi_fortran_statuses_ignore)
#elif OMPI_F77_SINGLE_UNDERSCORE
#define OMPI_IS_FORTRAN_BOTTOM(addr) \
(addr == (void*) &mpi_fortran_bottom_)
#define OMPI_IS_FORTRAN_IN_PLACE(addr) \
(addr == (void*) &mpi_fortran_in_place_)
#define OMPI_IS_FORTRAN_ARGV_NULL(addr) \
(addr == (void*) &mpi_fortran_argv_null_)
#define OMPI_IS_FORTRAN_ARGVS_NULL(addr) \
(addr == (void*) &mpi_fortran_argvs_null_)
#define OMPI_IS_FORTRAN_ERRCODES_IGNORE(addr) \
(addr == (void*) &mpi_fortran_errcodes_ignore_)
#define OMPI_IS_FORTRAN_STATUS_IGNORE(addr) \
(addr == (void*) &mpi_fortran_status_ignore_)
#define OMPI_IS_FORTRAN_STATUSES_IGNORE(addr) \
(addr == (void*) &mpi_fortran_statuses_ignore_)
#else
#define OMPI_IS_FORTRAN_BOTTOM(addr) \
(addr == (void*) &mpi_fortran_bottom__)
#define OMPI_IS_FORTRAN_IN_PLACE(addr) \
(addr == (void*) &mpi_fortran_in_place__)
#define OMPI_IS_FORTRAN_ARGV_NULL(addr) \
(addr == (void*) &mpi_fortran_argv_null__)
#define OMPI_IS_FORTRAN_ARGVS_NULL(addr) \
(addr == (void*) &mpi_fortran_argvs_null__)
#define OMPI_IS_FORTRAN_ERRCODES_IGNORE(addr) \
(addr == (void*) &mpi_fortran_errcodes_ignore__)
#define OMPI_IS_FORTRAN_STATUS_IGNORE(addr) \
(addr == (void*) &mpi_fortran_status_ignore__)
#define OMPI_IS_FORTRAN_STATUSES_IGNORE(addr) \
(addr == (void*) &mpi_fortran_statuses_ignore__)
#endif /* weak / specific symbol type */
/* Convert between Fortran and C MPI_BOTTOM */
#define OMPI_ADDR(addr) (OMPI_IS_FORTRAN_BOTTOM(addr) ? MPI_BOTTOM : (addr))
#define OMPI_IN_PLACE(addr) (OMPI_IS_FORTRAN_IN_PLACE(addr) ? MPI_IN_PLACE : (addr))
#endif /* OMPI_F77_CONSTANTS_H */