Skip to content

abi: clean up mpix.h, mpi_legacy.h and ABI exports - #8131

Merged
hzhou merged 20 commits into
pmodels:mainfrom
hzhou-muse:abi-headers
Nov 11, 2026
Merged

hzhou merged 20 commits into
pmodels:mainfrom
hzhou-muse:abi-headers

Conversation

@hzhou-muse

@hzhou-muse hzhou-muse commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Pull Request Description

In the MPI ABI build, the headers next to mpi.h did not fit together: mpix.h and mpi_legacy.h both declared removed MPI functions, several MPIX constants were missing or used values outside the MPI ABI encoding, and libmpi_abi had almost none of the MPIX functions, so mpicc -mpi-mpix programs failed to link. libmpi_abi also exported some removed MPI functions and internal MPIR_/MPII_ symbols (#7938).

This PR:

  • MPIX: mpix.h is MPIX only, with an explicit #ifdef MPI_ABI_VERSION branch. MPIX constants follow the MPI ABI encoding as if they were standard, MPIX_Stream and MPIX_Grequest_class become MPI ABI handles, and libmpi_abi provides all MPIX functions. The Fortran binding uses the MPIX callbacks on both ABIs.
  • Removed APIs: they stay real functions in the MPICH ABI. In the MPI ABI, mpi_legacy.h maps them to their replacements (the approach from binding/abi: update upstream mpi_abi.h #7948) and libmpi_abi exports none of them; MPI_LB/MPI_UB are not available there.
  • Internal symbols: MPIR_Err_* and MPII_Keyval_set_proxy are no longer exported; the C++ binding now uses the MPIX keyval callbacks.

Additional changes:

  • ROMIO no longer uses removed APIs (commit from binding/abi: update upstream mpi_abi.h #7948), and pvfs2 builds without MPI_LB/MPI_UB.
  • The test suite skips the MPI_LB/MPI_UB tests when mpi.h lacks them.
  • mpicc -mpix as an alias of -mpi-mpix.
  • New wiki page doc/wiki/design/MPI_Header.md on the three ways mpi.h is used; docs and CHANGES updated.
  • Remove a stray conflict marker from CHANGES.
  • Fixes found while testing: mpicxx now links libmpicxx (configure tested the string enable_cxx), the MPI ABI get_file_errhand() returns its result, and the MPI ABI collective wrappers size per-peer arrays by threads on a threadcomm.
  • The test suite runs the impls/mpich (MPIX) tests on MPICH's MPI ABI, with -mpi-mpix.

Addresses #7938. Supersedes #7948.

plan.md

MPI ABI header cleanup: mpix.h, mpi_legacy.h, mpi_fortran.h

Plan and notes for this PR, with local testing results.

Header layout (on the branch)

Header MPICH native ABI MPI ABI (-DMPI_ABI)
mpix.h always (MPI_MPIX forced) with mpicc -mpi-mpix
mpi_legacy.h not used; removed APIs are real functions declared in mpi.h/mpi_proto.h with mpicc -mpi-legacy: macros + static inline
mpi_fortran.h with mpicc -mpi-fortran with mpicc -mpi-fortran
  • Three modes of mpi.h: MPI ABI header, MPICH ABI header, libmpi_abi build
    (MPICH_BUILD_MPI_ABI); documented in doc/wiki/design/MPI_Header.md.
  • libmpi_abi wrappers convert handle types; everything else passes through. The library is
    compiled with the ABI integer constants (mpi_abi_internal.h, generated by gen_abi.py from
    mpi_abi.h and mpix.h) and native handles. Callbacks taking handles are converted at their
    call sites (reduce_local.c, errutil.c, attrutil.c).

Decisions

  1. mpix.h is MPIX only; removed APIs are only in mpi_legacy.h (MPI ABI) / mpi_proto.h (native).
  2. MPICH identifies MPICH headers in every mode; MPI_ABI_VERSION identifies the MPI ABI.
    No MPICH_NATIVE_ABI for now.
  3. mpix.h: explicit #ifdef MPI_ABI_VERSION / #else. The ABI branch defines the MPIX constants
    that differ between ABIs (converted handles); the native branch is a comment (values in
    mpi.h). Pass-through constants with no conflict are defined once in the common section.
  4. MPIX constants are treated as if standard: values fit the MPI ABI encoding and go through the
    regular conversions. MPIX_C_FLOAT16/MPIX_BFLOAT16 0x24a/0x24b (2-byte C), MPIX_EQUAL 0x3e.
    MPIX handle categories are allocated from the back: MPIX_Stream 11111 (MPIX_STREAM_NULL
    0x1f8), MPIX_Grequest_class 11110 (no null constant; generator initializes outputs with 0).
    MPIX_ERR_* 101-107 (MPICH encodes error classes in 7 bits, so not above 16384 as MPI 5.0
    asks); MPIX_COMM_TYPE_NEIGHBORHOOD 5 in both ABIs (no clash with 1-4 native, 221-224 ABI).
  5. libmpi_abi provides all MPIX functions. The Fortran binding uses the MPIX callbacks on both
    ABIs (HAS_MPIX_CALLBACKS, independent of --disable-fortran-mpix); Fortran MPIX routines on
    the MPI ABI are a follow-up.
  6. Removed APIs: always available as real functions in the MPICH native ABI; in the MPI ABI,
    mpi_legacy.h maps them to replacements (from binding/abi: update upstream mpi_abi.h #7948) and libmpi_abi exports none of them.
    MPI_LB/MPI_UB are not provided in the MPI ABI (compile-time error).

Commits

See the commit list of the PR.

#7938 internal exports (done in the errhan and binding/cxx commits; checked with nm): the MPICH_API_PUBLIC
markers on MPIR_Err_* and MPII_Keyval_set_proxy date from 29fb99d (2016, for the binding
libraries); their users are now inside the same library (ROMIO, io_abi.c) or moved to MPIX callbacks
(C++). MPIR_fortran_{true,false} were already hidden (27d6d79). Intentionally exported:
MPID_Recvq_*_head_ptr (debugger), MPIR_F08_MPI_STATUS(ES)_IGNORE_OBJ (libmpifort, bound from
the f08 module), QMPI_*, MPIR_Call_world_errhand/MPIR_CXX_InitDatatypeNames (libmpicxx,
referenced from mpicxx.h). The C++ attr proxies in libmpicxx are static.

Open

  • Handle values in reserved slots: MPIX handles (0x24a, 0x24b, 0x3e, 0x1f8, category 11110)
    sit in ranges the standard reserves. Ask the Forum for an implementation range?
  • mpi.h does not define MPI_Fint by default — is this intended and what should packages do? #7973 MPI_Fint: packages can't detect the need for -mpi-fortran (feature macro? CMake
    FindMPI guidance).
  • Duplicate native MPIX prototypes: mpix.h and mpi_proto.h both declare them; compatible,
    but two lists to keep in sync (they match now).

Follow-ups (probably outside this PR)

  • Fortran MPIX routines on the MPI ABI: f08 kind for MPIX_Stream/MPIX_Grequest_class
    (pointers in the ABI; binding_f08.py defaults to c_int), *_attr_as_fortran paths.
  • General test-suite gate for removed APIs (only if an MPI without -mpi-legacy is targeted).
  • Fortran allctypesf.f/allctypesf08.f90 use MPI_LB, which the Fortran binding never had on
    the MPI ABI (pre-existing).
  • mpicc man page for -mpi-mpix, -mpi-legacy, -mpi-fortran (wiki and CHANGES done).
  • PR binding/abi: update upstream mpi_abi.h #7948: this PR takes over its approach and its ROMIO commit.

Testing plan

Done so far (generator only, no build): c_binding_abi.c checked before/after each generator
change — unchanged except the intended wrappers (MPIX_Stream handle and removed-function commits); mpi_abi_internal.h
diffs checked for the MPIX constants and mpi_legacy.h commits.

Modes

  • Mode 1a: MPI ABI header without -mpi-mpix (mpicc_abi) — no MPIX symbol visible.
  • Mode 1b: MPI ABI header with -mpi-mpix (mpicc_abi -mpi-mpix).
  • Mode 2: MPICH ABI header (mpicc; also the libmpi build).
  • Mode 3: libmpi_abi build (-DMPICH_BUILD_MPI_ABI; mpi_abi_internal.h + native mpi.h).

MPIX coverage table (expected; verify against it)

Symbol(s) Kind Mode 1b Mode 2 Mode 3 (library build)
MPIX_Stream handle type struct MPIX_ABI_Stream * (mpix.h ABI branch) int (mpi.h.in) native int; ABI_Stream for wrappers
MPIX_STREAM_NULL handle constant 0x1f8 0x3c000000 native; ABI_STREAM_NULL 0x1f8
MPIX_C_FLOAT16, MPIX_BFLOAT16 datatype constants 0x24a, 0x24b 0x4c000246, 0x4c00024c native; ABI_* in datatype table
MPIX_EQUAL op constant 0x3e 0x5800000f native; ABI_EQUAL in op table
MPIX_Grequest_class handle type, no predefined handles struct MPIX_ABI_Grequest_class * (category 11110) int (mpi.h.in) native int; ABI_Grequest_class for wrappers
MPIX_Async_thing opaque pointer same same same, pass-through
MPIX_Iov struct same same same
MPIX_User_function_x, MPIX_{Comm,Win,File,Session}_errhandler_function_x callback typedefs with handles ABI handle types native types ABI_ types; handles converted at call sites
MPIX_Destructor_function, MPIX_Grequest_{poll,wait}_function, MPIX_Async_poll_function callback typedefs, no handles same same same
MPIX_ERR_* (101-107), MPICH_ERR_FIRST/LAST_MPIX (100/107) int mpix.h common same same (internal header)
MPIX_COMM_TYPE_NEIGHBORHOOD int 5 5 5
MPIX_GPU_SUPPORT_* (0-2), MPIX_ASYNC_* (0-1) int / enum same same same
MPIX/PMPIX prototypes declarations mpix.h, ABI types mpix.h + mpi_proto.h internal header, ABI_ types + MPICH_API_PUBLIC
MPIX_Stream_c2f/f2c Fortran interop mpi_fortran.h (with -mpi-fortran) same — (libmpifort)
removed MPI APIs — mpi_legacy.h with -mpi-legacy: macros/inline, no MPI_LB/UB (compile error) mpi_proto.h, real functions incl. MPI_LB/UB none (gen_abi does not read mpi_legacy.h)

Libraries: libmpi exports all MPIX_/PMPIX_ (incl. _c); libmpi_abi the same except the
c2f/f2c functions (Fortran binding). Fortran: MPIX routines on the MPICH ABI only (unless
--disable-fortran-mpix); HAS_MPIX_CALLBACKS on both ABIs.

T0 Builds (end-to-end matrix)

Build configure Modes exercised
MPICH ABI --enable-mpi-abi=no (default) 2
MPI ABI --enable-mpi-abi=yes 1a, 1b, 3
Dual --enable-mpi-abi=dual 1a, 1b, 2, 3
Stand-alone Fortran src/binding/fortran against the MPI ABI install, and with --disable-fortran-mpix Fortran config

Each build with --enable-strict; check no macro redefinition warnings from mpi_abi_internal.h.

T1 Header symbol exposure (per mode, C and C++)

Generate a probe from the coverage table: #ifndef X / #error for each macro,
_Static_assert on each value, sizeof/_Generic on each type, (void)&MPIX_fn for each
prototype (all 66+ MPIX and PMPIX). Compile in 1a (expect every MPIX symbol absent), 1b, 2 with
mpicc/mpicc_abi/mpicxx. Mode 3: compile the probe with the library's CPPFLAGS
(-DMPICH_BUILD_MPI_ABI) and inspect mpi_abi_internal.h.

T2 Binary symbol check (nm)

  • nm -D --defined-only on libmpi.so and libmpi_abi.so: diff the MPIX_/PMPIX_ set against the
    generator's function list (incl. _c variants; c2f/f2c excluded for libmpi_abi).

  • libmpifort on the MPI ABI: nm -u shows MPIX_Op_create_x, MPIX_Comm_create_keyval_x,
    MPIX_Comm_create_errhandler_x (HAS_MPIX_CALLBACKS); no MPIX_ Fortran routines exported.

  • No removed-API symbol in libmpi_abi.so (MPI_Address, MPI_Type_extent, MPI_Attr_, MPI_Keyval_,
    MPI_Errhandler_{create,get,set}, MPI_Type_{hindexed,hvector,struct,lb,ub}); libmpi.so still has them.

  • No MPIR_/MPII_ symbol exported from libmpi.so or libmpi_abi.so.

T3 Spot-check APIs (run on libmpi and libmpi_abi; dual build covers both)

Existing tests: impls/mpich/comm/stream.c, stream_comm.c, stream_multiplex.c
(MPIX_Stream arrays); impls/mpich/misc/type_float16.c (MPIX_C_FLOAT16);
comm/cmsplit_type.c (NEIGHBORHOOD); ft/revoke_nofail.c (ULFM, MPIX_ERR_*);
impls/mpich/misc/gpu_query.c. Fortran user op/attr on the ABI: f77/coll/uallreducef.f,
reducelocalf.f, f77/attr/commattrf.f.

New small tests (no existing coverage): MPIX_Op_create_x (callback datatype equals the
caller's MPI_INT), MPIX_Comm_create_errhandler_x (callback comm equals the caller's comm),
MPIX_Comm_create_keyval_x (copy/delete/destructor called), MPIX_Async_start,
MPIX_Grequest_class_create, MPIX_Info_set_hex, MPIX_Stream_toint(MPIX_STREAM_NULL).
C++ keyvals via MPIX keyval_x (MPICH ABI): cxx/attr/attrtx, fkeyvalcommx, cxx/rma/fkeyvalwinx,
incl. NULL_COPY_FN/DUP_FN and Free_keyval.

Removed APIs on the MPI ABI (mpicc_abi -mpi-legacy): the attr/, errhan/commcall_oldapi,
datatype/oldapi and errors/datatype/type_nullarg tests build and pass via the macro mapping;
MPI_LB in a test program fails to compile; lbub_oldapi, typename_oldapi, struct_no_real_types
are skipped (configure reports MPI_LB and MPI_UB... no).

T4 CI

test:mpich/custom with config: mpi-abi, test:mpich/ch4/ofi, test:mpich/ch3/tcp.

Testing results

Builds (autogen + configure, --enable-strict, dataloop): ch3 MPICH ABI (Fortran, C++), ch3 MPI ABI
(in-tree Fortran), ch3 dual (--disable-fortran), ch4:ofi dual; stand-alone Fortran against the
dual install (--enable-mpi-abi) and against the MPICH install (--disable-fortran-mpix).
No new warnings (pre-existing: type_create* maybe-uninitialized; ABI-only errhan_file.c, type_debug.c).

Found and fixed (folded into their commits, pushed):

  • maint/extracterrmsgs read MPICH_ERR_LAST_MPIX from mpi.h.in -> autogen failed; now reads mpix.h too
    (generated error table identical to main).
  • MPIX_Async_get_state (returns void *) was missing from mpix.h, its ABI wrapper returned void
    (compile error), and gen_abi didn't mark void * prototypes public.
  • C++ keyvals: MPIX_*_create_keyval_x rejects NULL callbacks, so NULL_COPY_FN/NULL_DELETE_FN broke;
    the proxies now handle them.
  • test/mpi/impls/mpich/comm/stream_multiplex.c: forward declaration of test_stream_send had the
    wrong parameter type (MPIX_Stream vs MPI_Comm), exposed by MPIX_Stream being a pointer in the ABI.

Results:

  • T1: probe passes in modes 1a/1b/2 on all installs (-mpi-mpix, -mpix, -mpi-legacy, mpicc_abi,
    mpicc -mpi-abi); MPI_LB is a compile error on the MPI ABI only; C++ compiles in all.
  • T2: libmpi.so and libmpi_abi.so export all 138 MPIX/PMPIX functions; libmpi_abi.so: no removed API,
    no MPIR_/MPII_; libmpi.so: 30 removed-API symbols, MPIR_Dup_fn only (MPI_DUP_FN); libmpicxx and
    libmpifort (both ABIs) use the MPIX _x callbacks.
  • T3: spot.c (18 checks incl. streams on ch4) and legacy.c pass on libmpi and libmpi_abi (ch3 and ch4);
    test suite: attr/*, _oldapi, errhan/commcall_oldapi, errors/datatype/_nullarg, cmsplit_type,
    f77 user op/attr tests pass on both ABIs; MPI_LB tests skipped on the MPI ABI by the new gate;
    cxx/attr + cxx/rma keyval tests pass; impls/mpich stream, stream_comm, stream_multiplex,
    type_float16, gpu_query pass on libmpi_abi with -mpix; f77 tests built on one libmpi_abi run on
    the stand-alone libmpifort + the dual build's libmpi_abi.
  • Not covered: ft/revoke_nofail (xfail ticket2237 in its testlist); 4 ranks x 4 reserved VCIs on ch4
    dies (SIGBUS/kill) on both ABIs in this container, so streams ran with 1-2 reserved VCIs.

Pre-existing issues found on main, fixed in this PR (commits after the C++ keyval commit):

  • mpicxx: link the C++ binding library -- configure tested the string "enable_cxx"; -lmpicxx is now
    added only on the MPICH ABI (mpicxx_abi / mpicxx -mpi-abi link only -lmpi_abi). Verified: link
    lines, test-suite C++ probe "yes", cxx/attr, cxx/rma, cxx/coll tests pass.
  • errhan: get_file_errhand (MPI ABI) returns its result; -Wreturn-type warning gone.
  • test: impls/mpich enabled on MPICH's MPI ABI when MPIX links with -mpi-mpix. Running it exposed
    binding/abi: ABI_Comm_rank/ABI_Comm_peer_size ignored threadcomms, so MPI_Alltoallw on a
    threadcomm failed ("Invalid datatype"); fixed. impls on the MPI ABI: ch3 20/20, ch4 28/29; the one
    failure, comm_info_hint, fails the same way on the MPICH ABI (pre-existing, not addressed).

Author Checklist

  • Provide Description
  • Commits Follow Good Practice
  • Passes All Tests
  • Contribution Agreement

Model: Claude Opus 5.5

@hzhou-muse

Copy link
Copy Markdown
Contributor Author

@dalcinl Thanks for the libabigail review in #7938 and the proposal in #7948. This PR addresses both:

  • Removed APIs: libmpi_abi no longer exports any of them. With -mpi-legacy, mpi_legacy.h uses your macro/static-inline mapping to the replacement functions (with the PMPI_Get_address and PMPI_Comm_create_errhandler names fixed), and your ROMIO commit is included. The MPICH ABI keeps them as real functions for backward compatibility.
  • MPI_LB/MPI_UB: not provided on the MPI ABI, so using them is a compile-time error. They only work if the library interprets the markers, which a standard libmpi_abi need not do.
  • MPIX: mpix.h is for the MPIX namespace only and stays opt-in on the MPI ABI (-mpi-mpix, or the new -mpix). libmpi_abi now provides all the MPIX functions, and the MPIX constants and handles follow the MPI ABI encoding.
  • Internal symbols: MPIR_Err_* and MPII_Keyval_set_proxy are no longer exported; MPIR_fortran_{true,false} were already hidden by your 27d6d79. QMPI_* stay, as MPICH's tool interface.

This PR takes over #7948, so I think #7948 can be closed once this is merged.

@hzhou-muse

Copy link
Copy Markdown
Contributor Author

Local testing results (be96b2d).

Builds (autogen + configure, --enable-strict, dataloop): ch3 MPICH ABI (with Fortran and C++), ch3 MPI ABI (with in-tree Fortran), ch3 dual, ch4:ofi dual, and the stand-alone Fortran binding against libmpi_abi and with --disable-fortran-mpix. No new warnings.

Fixed while testing (folded into their commits):

  • maint/extracterrmsgs read MPICH_ERR_LAST_MPIX from mpi.h.in, which broke autogen after the move to mpix.h; it now reads both, and the generated error table is identical to main.
  • MPIX_Async_get_state was missing from mpix.h, and its ABI wrapper returned void instead of void *.
  • C++ Create_keyval with NULL_COPY_FN/NULL_DELETE_FN: MPIX_*_create_keyval_x requires non-null callbacks, so the C++ proxies now handle the null cases.
  • stream_multiplex.c declared test_stream_send with an MPIX_Stream instead of an MPI_Comm parameter, which only shows now that MPIX_Stream is a distinct type in the MPI ABI.

Results

  • Headers: checked in each mode (mpicc, mpicc_abi, mpicc -mpi-abi, with and without -mpi-mpix/-mpix/-mpi-legacy): MPIX types and constant values as expected, no MPIX symbols on the MPI ABI without -mpi-mpix, MPI_LB is a compile error on the MPI ABI only, C++ compiles.
  • Symbols: libmpi.so and libmpi_abi.so both export all MPIX functions; libmpi_abi.so exports no removed MPI function and no MPIR_/MPII_ symbol; libmpicxx and libmpifort (both ABIs) use the MPIX _x callbacks.
  • Run on both libmpi and libmpi_abi: MPIX op/errhandler/keyval _x callbacks, async, grequest class, MPIX_Info_set_hex, streams (ch4), the removed APIs with -mpi-legacy; test suite attr/, *_oldapi, errhan/commcall_oldapi, errors/datatype/*_nullarg, comm/cmsplit_type, f77 user op and attribute tests; impls/mpich stream, stream_comm, stream_multiplex, type_float16, gpu_query on libmpi_abi with -mpix; C++ cxx/attr and cxx/rma keyval tests. The MPI_LB/MPI_UB tests are skipped on the MPI ABI by the new configure check.
  • f77 tests built on one libmpi_abi also run with the stand-alone libmpifort and the dual build's libmpi_abi.

Not covered: ft/revoke_nofail (xfail in its testlist), and 4 ranks with 4 reserved VCIs on ch4, which fails the same way on both ABIs in my container, so the stream tests ran with 1-2 reserved VCIs.

Pre-existing issues on main, not addressed here:

  • configure.ac: if test "enable_cxx" = "yes" is missing the $, so mpicxx never links -lmpicxx.
  • src/mpi/errhan/errhan_file.c: the MPI ABI get_file_errhand() does not return a value.
  • The test suite does not enable the impls/ MPIX tests on the MPI ABI; it could now with -mpi-mpix.

@hzhou-muse
hzhou-muse force-pushed the abi-headers branch 2 times, most recently from 6bc227e to 16e9ee1 Compare November 10, 2026 00:33
@hzhou

hzhou commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator

@dalcinl @hppritcha One issue after another, the PR got more complex than its initial scope. The end results for MPI ABI build:

  • libmpi_abi.so no longer contain legacy API symbols or previous leaked MPII_/MPIR_ symbols. It does contain all the MPIX_ symbols as well as the QMPI_ symbols.
  • mpi.h in ABI mode only exposes standard APIs.
    • -mpi-legacy enables @dalcinl 's legacy wrappers except MPI_LB/UB. It is a compile error to use LB/UB in MPI ABI
    • -mpi-fortran pulls in mpi_fortran.h, to be supplied by a Fortran binding
    • -mpi-mpix enables mpich-specific MPIX APIs. Doing so necessarily break the ABI portability.

@hzhou hzhou added the 5.1.x label Nov 10, 2026
@hzhou

hzhou commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator

test:mpich/ch3/most
test:mpich/ch4/most

- [Overriding Collective Functions](Overriding_Collective_Functions.md)

- Language Bindings
- [The mpi.h Header](MPI_Header.md)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- [The mpi.h Header](MPI_Header.md)
- [The `mpi.h` Header](MPI_Header.md)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Applied, and the page heading now matches.

Comment thread doc/wiki/design/MPI_Header.md Outdated
Comment on lines +45 to +47
#include "mpix.h"
#include <mpi_proto.h>
mpicxx.h (C++)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although probably inconsequential, why is mpix.h first here? Comparing to the ABI path, it should be after the standard prototypes. Also, why isn't mpi_proto.h included with quotes as all the other headers?

In short, shouldn't all be the following way?

Suggested change
#include "mpix.h"
#include <mpi_proto.h>
mpicxx.h (C++)
#include "mpi_proto.h"
#include "mpix.h"
#include "mpicxx.h" if C++

Of course, any changes to this doc file should be applied to mpi.h.in.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The order is intentional: in the MPICH ABI, mpi_proto.h also declares the MPIX functions, whose types (MPIX_Stream, MPIX_Iov, ...) are defined in mpix.h, so mpix.h must come first. I added a note to the doc. Switched mpi_proto.h to quotes in mpi.h.in and the doc, and replaced the mpicxx.h line with a proper include.

Comment thread src/include/mpi_legacy.h Outdated
Comment on lines +40 to +42
#define MPI_COMBINER_HVECTOR_INTEGER MPI_COMBINER_HVECTOR
#define MPI_COMBINER_HINDEXED_INTEGER MPI_COMBINER_HINDEXED
#define MPI_COMBINER_STRUCT_INTEGER MPI_COMBINER_STRUCT

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hzhou Please look at this comment from Copilot AI.
mpi-forum/mpi-abi-stubs#103 (comment)

I think the complaint is valid, having duplicate combiner values in a switch statement will lead to compile errors.

There are two options here:

  1. Do not provide these defines, like done for MPI_LB/UB
  2. Define them to values that will not overlap with other combiners. Look for example what I'v done in Add header collecting backward compatibility for removed MPI APIs mpi-forum/mpi-abi-stubs#103
#define MPI_COMBINER_HVECTOR_INTEGER   (MPI_COMBINER_NAMED-1)
#define MPI_COMBINER_HINDEXED_INTEGER  (MPI_COMBINER_NAMED-2)
#define MPI_COMBINER_STRUCT_INTEGER    (MPI_COMBINER_NAMED-3)

I think this is fine, we know that MPI ABI implementations will NEVER produce datatypes with these combiner values. Any outdated switch statement will keep compiling and the case statements will simply be runtime-uncovered code.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Went with option 2, using the same values as mpi-forum/mpi-abi-stubs#103, so legacy switch cases compile and are simply never taken.

@dalcinl

dalcinl commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator

@hzhou The MPICH test suite assumes at least MPI 2.0, right? If that is correct, then maybe this PR is a good opportunity to fix some or all of the following:

$ git grep MPI_NULL_ test/
test/mpi/attr/attrdelete.c:    MPI_Comm_create_keyval(MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN, &key1, NULL);
test/mpi/attr/attrdelete.c:    MPI_Comm_create_keyval(MPI_NULL_COPY_FN, key2_delete_fn, &key2, NULL);
test/mpi/attr/attrdelete.c:    MPI_Comm_create_keyval(MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN, &key3, NULL);
test/mpi/attr/attrdeleteget.c:    MPI_Comm_create_keyval(MPI_NULL_COPY_FN, delete_fn, &key, &errs);
test/mpi/attr/attrend.c:    MPI_Keyval_create(MPI_NULL_COPY_FN, delete_fn, &exit_key, (void *) 0);
test/mpi/attr/attric.c:        MPI_Keyval_create(MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN, &key_3, &value);
test/mpi/attr/attrorder.c:            MPI_Keyval_create(MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN, &key[i], (void *) 0);
test/mpi/attr/attrordercomm.c:            MPI_Comm_create_keyval(MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN, &key[i], (void *) 0);
test/mpi/attr/attrt.c:        MPI_Keyval_create(MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN, &key_3, &value);
test/mpi/attr/fkeyval.c:            MPI_Keyval_create(MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN, &key[i], (void *) 0);
test/mpi/attr/fkeyvalcomm.c:            MPI_Comm_create_keyval(MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN, &key[i], (void *) 0);
test/mpi/attr/keyval_double_free.c:    MPI_Keyval_create(MPI_NULL_COPY_FN, delete_fn, &keyval, NULL);
test/mpi/attr/keyval_double_free_comm.c:    MPI_Comm_create_keyval(MPI_NULL_COPY_FN, delete_fn, &keyval, NULL);
test/mpi/f77/attr/attrmpi1f.f:      call mpi_keyval_create( MPI_NULL_COPY_FN, MPI_NULL_DELETE_FN,
test/mpi/f77/attr/commattr4f.f:     $     MPI_NULL_DELETE_FN,
test/mpi/impls/mpich/threads/threadcomm/threadcomm_attr.c:    MPI_Comm_create_keyval(MPI_NULL_COPY_FN, key_delete_fn, &key, NULL);
test/mpi/init/attrself.c:        MPI_Comm_create_keyval(MPI_NULL_COPY_FN, delete_fn, &key[nkeys], (void *) 0);

@hzhou

hzhou commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator

The MPICH test suite assumes at least MPI 2.0, right?

I am not sure. I think we are still supporting MPI 1 applications.

@dalcinl

dalcinl commented Nov 10, 2026

Copy link
Copy Markdown
Collaborator

The MPICH test suite assumes at least MPI 2.0, right?

I am not sure. I think we are still supporting MPI 1 applications.

But then some of the tests should fail to compile, For example
test/mpi/errors/attr/keyvalmis.c
Or is this test being somehow disabled if MPI_VERSION >= 2 ?

@hzhou

hzhou commented Nov 10, 2026 •

Copy link
Copy Markdown
Collaborator

The MPICH test suite assumes at least MPI 2.0, right?
I am not sure. I think we are still supporting MPI 1 applications.
But then some of the tests should fail to compile, For example test/mpi/errors/attr/keyvalmis.c Or is this test being somehow disabled if MPI_VERSION >= 2 ?

AI help me 🤣 :

Where the two of you are talking past each other:

  • What he asked: whether the test suite can assume the implementation under test is MPI-2 or newer. If so, tests that pair MPI-2 calls with MPI-1 constants could switch to the MPI-2 names. For example, MPI_Comm_create_keyval(MPI_NULL_COPY_FN, ...) in attrdelete.c, attrordercomm.c, fkeyvalcomm.c, init/attrself.c and threadcomm_attr.c could use MPI_COMM_NULL_COPY_FN.
  • What you answered: that MPICH the library still supports MPI-1 applications, meaning it keeps the deprecated APIs. That's true, but it doesn't stop the tests from assuming MPI-2.

A possible reply: agree that the test suite assumes MPI-2, and fix the mixed cases, i.e. MPI-2 create_keyval calls that pass MPI_NULL_FN. Keep the tests that deliberately exercise the MPI-1 API, such as MPI_Keyval_create in attrt.c, attric.c, attrorder.c, fkeyval.c, attrend.c, keyval_double_free.c and f77/attr/attrmpi1f.f, because they're what tests MPICH's
backward compatibility. On the MPI ABI those would need -mpi-legacy.

[From me]: I am not insisting of such tests, but I see some plausibility of keep testing old APIs. As I said, I am not sure yet.

hzhou-muse and others added 9 commits November 10, 2026 21:30
mpix.h now defines the MPIX constants for the MPI ABI together under
"#ifdef MPI_ABI_VERSION", with values that follow the MPI ABI encoding
as if they were standard constants: MPIX_C_FLOAT16 and MPIX_BFLOAT16 in
the 2-byte C datatype category, and MPIX_EQUAL in the other-operations
category. They go through the regular gen_abi conversions; mpi.h keeps
the native values.

MPIX constants that are passed through unconverted and don't conflict
with either ABI are defined once in mpix.h for both ABIs, moved from
mpi.h: the MPIX error classes, which stay at 101-107 since MPICH
encodes error classes in 7 bits, and MPIX_COMM_TYPE_NEIGHBORHOOD (5).

mpix.h also declares MPIX_Stream_toint, MPIX_Stream_fromint and
MPIX_Async_get_state, and gen_abi.py recognizes prototypes returning
MPIX types and void *, so they are declared with MPICH_API_PUBLIC in
mpi_abi_internal.h.

maint/extracterrmsgs reads the MPIX error classes from mpix.h as well.

Previously the ABI constants were guarded by "#ifndef MPICH", which has
been dead since mpi.h always defines MPICH, and MPIX_STREAM_NULL,
MPIX_COMM_TYPE_NEIGHBORHOOD and MPIX_ERR_* were missing in MPI ABI mode.

Model: Claude Opus 5.5
Functions removed from the MPI standard are declared only in
mpi_legacy.h for the MPI ABI, and in mpi_proto.h for the MPICH native
ABI. mpix.h is for MPIX extensions only. Update the mpi_legacy.h header
comment to match.

Previously mpix.h declared a subset of the removed functions, so an MPI
ABI user with only -mpi-mpix got half of the legacy API, and both
headers declared them with -mpi-mpix -mpi-legacy.

Model: Claude Opus 5.5
In the MPI ABI, MPIX_Stream and MPIX_Grequest_class are now opaque
handles like the standard handles. MPIX_STREAM_NULL is in handle
category 0b0001_11111 and MPIX_Grequest_class takes 0b0001_11110,
without predefined handles: MPIX handle categories are allocated from
the back to avoid collisions with new standard handles. libmpi_abi
converts them with ABI_Stream_to_mpi/from_mpi and
ABI_Grequest_class_to_mpi/from_mpi, and the binding generators treat
them as handle types. The native typedefs move to mpi.h, next to
MPIX_STREAM_NULL.

Fix the stream_multiplex test, whose forward declaration of
test_stream_send took an MPIX_Stream instead of the MPI_Comm of its
definition.

Previously both were ints in both modes, and the MPI ABI used the
native MPIX_STREAM_NULL value.

Model: Claude Opus 5.5
libmpi_abi now provides all the MPIX functions. The generated ABI
wrappers convert their handle arguments like the standard ones; the
callbacks that take handles are already converted where the library
calls them. MPIX_Waitall_enqueue is added to the request-array
conversions.

The Fortran configure now identifies the MPI ABI by the library it
picked rather than by the absence of MPIX functions, and still keeps
MPIX off in the Fortran binding on the MPI ABI.

Previously libmpi_abi only had the MPIX functions ROMIO needs
(MPIX_Grequest_* and MPIX_Type_iov*), so MPI ABI programs using
"mpicc -mpi-mpix" failed to link.

Model: Claude Opus 5.5
The Fortran binding now uses the MPIX callbacks (MPIX_Op_create_x,
MPIX_*_create_keyval_x, MPIX_*_create_errhandler_x) for its
user-function proxies whenever the C library provides them, including
libmpi_abi, and independent of --disable-fortran-mpix, which only
controls the MPIX routines for Fortran users. MPI_MPIX is defined with
them so that mpi.h provides the declarations on the MPI ABI.

Previously the callbacks were off on the MPI ABI, so a Fortran user op
received an MPI ABI datatype handle instead of a Fortran integer, and
the keyval and errhandler proxies had no cleanup.

Model: Claude Opus 5.5
Remove usage of:

* MPI_Copy_function
* MPI_Delete_function
* MPI_NULL_COPY_FN
libmpi_abi no longer has wrappers for the functions removed from the
MPI standard, such as MPI_Address, MPI_Type_extent and MPI_Attr_get.
The MPI ABI does not include them, and a program built against the MPI
ABI should not depend on them.

This temporarily breaks "mpicc -mpi-legacy" for the MPI ABI: mpi_legacy.h
still declares the removed functions, so programs using them, including
the removed-API tests in test/mpi, fail to link. The next commit maps
them to their replacements in mpi_legacy.h.

Previously libmpi_abi exported the removed functions, which made
programs that use them run only on MPICH's libmpi_abi.

Model: Claude Opus 5.5
The pvfs2 driver checks for the MPI_LB and MPI_UB markers only when
mpi.h provides them. They were removed from the MPI standard and the
MPI ABI does not have them, so without them no datatype can contain
the markers.

Previously the driver required MPI_LB and MPI_UB to compile.

Model: Claude Opus 5.5
hzhou-muse and others added 4 commits November 10, 2026 21:44
In the MPI ABI, mpi_legacy.h now maps the APIs removed from the MPI
standard to their replacements with macros, and implements
MPI_Type_extent/lb/ub as static inline functions, so a program built
with "mpicc -mpi-legacy" needs no removed symbol from the library and
stays portable across MPI ABI implementations. MPI_LB and MPI_UB are
not provided, so using them is a compile-time error: the markers only
work if the library interprets them, which a standard libmpi_abi need
not do. In the MPICH native ABI the removed APIs, including MPI_LB and
MPI_UB, stay real and always available, declared in mpi.h and
mpi_proto.h.

gen_abi.py no longer reads mpi_legacy.h, which has nothing the
libmpi_abi build needs.

The header follows the one proposed in pmodels#7948, with the
PMPI_Get_address and PMPI_Comm_create_errhandler names fixed.

Previously mpi_legacy.h declared the removed functions as prototypes
of functions in libmpi_abi, and gave MPI_LB and MPI_UB MPI ABI handle
values.

Co-authored-by: Lisandro Dalcin <dalcinl@gmail.com>
Model: Claude Opus 5.5
configure checks whether mpi.h provides MPI_LB and MPI_UB, which the MPI
ABI does not even with -mpi-legacy, and builds and runs lbub_oldapi,
typename_oldapi and struct_no_real_types only when it does.

Previously these tests failed to compile against the MPI ABI.

Model: Claude Opus 5.5
The compiler wrappers now accept -mpix as a shorter form of -mpi-mpix,
which makes mpi.h include mpix.h on the MPI ABI.

Model: Claude Opus 5.5
MPIR_Err_create_code and the MPIR_Err_return_* functions are no longer
exported from libmpi and libmpi_abi. Their only users outside the error
handling code are ROMIO and io_abi.c, which are linked into the same
library. Also remove the declaration of MPIR_Err_return_file, which is
not defined anywhere and was guarded by the never-defined
MPI__FILE_DEFINED.

Previously these internal functions were exported for the language
binding libraries, which no longer use them.

Model: Claude Opus 5.5
hzhou-muse and others added 7 commits November 10, 2026 21:44
The C++ binding now creates keyvals with MPIX_*_create_keyval_x, passing
the user's C++ copy and delete functions in the extra_state and freeing
it in the destructor, as it already does for user ops and errhandlers.
The proxies handle NULL_COPY_FN and NULL_DELETE_FN themselves, since
MPIX_*_create_keyval_x requires non-null callbacks.
MPII_Keyval_set_proxy has no other user and is removed, so libmpi no
longer exports it.

Previously the C++ binding installed its proxies with the internal
MPII_Keyval_set_proxy, which libmpi had to export.

Model: Claude Opus 5.5
mpicxx links libmpicxx when the C++ binding is built, and only for the
MPICH ABI, since the C++ binding does not exist for the MPI ABI
(mpicxx_abi, mpicxx -mpi-abi).

Previously configure tested the literal string "enable_cxx" instead of
$enable_cxx, so LMPICXXLIBNAME was always empty and C++ programs using
the C++ binding failed to link.

Model: Claude Opus 5.5
The MPI ABI version of get_file_errhand now returns the result of
MPIR_ROMIO_Get_file_errhand, and initializes the errhandler so that it
is not read uninitialized when the call fails.

Previously the function had no return statement (-Wreturn-type in the
MPI ABI build).

Model: Claude Opus 5.5
ABI_Comm_rank and ABI_Comm_peer_size, which the MPI ABI wrappers use to
size the per-peer arrays of collectives such as MPI_Alltoallw, now count
threads on a threadcomm, as MPI_Comm_rank and MPI_Comm_size do.

Previously they returned the process rank and size, so MPI_Alltoallw on
a threadcomm converted too few datatypes and failed with "Invalid
datatype".

Model: Claude Opus 5.5
When testing MPICH's MPI ABI, configure checks that the MPIX functions
link with -mpi-mpix, then adds the flag and enables the impls/mpich
tests, which exercise the MPIX extensions.

Previously impls/mpich was enabled only for the MPICH ABI, since
libmpi_abi did not provide the MPIX functions.

Model: Claude Opus 5.5
Include mpi_proto.h with quotes, like the other MPICH headers mpi.h
includes. Previously it used angle brackets.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add a design page describing the three modes in which mpi.h is
consumed: the MPI ABI header, the MPICH ABI header, and the header for
building libmpi_abi, how mpi.h.in is laid out for them, what the
generated mpi_abi_internal.h provides in the library build, and the
rules for editing mpi.h.in and mpix.h.

Describe how -mpi-legacy maps the removed APIs to their replacements on
the MPI ABI and that MPI_LB and MPI_UB are not available there, and add
a CHANGES entry. Mention the -mpix alias of -mpi-mpix.
Update the stand-alone Fortran binding page for the MPIX callbacks now
being independent of --disable-fortran-mpix.

Model: Claude Opus 5.5
@dalcinl

dalcinl commented Nov 11, 2026

Copy link
Copy Markdown
Collaborator

LGTM.

Now abidiff is happy. The following check could be easily incorporated in CI.

$ cat mpiabi.suppr
[suppress_function]
  change_kind = added-function
  name_regexp = ^(P?MPIX|QMPI)_.*

$ abidiff --suppr=mpiabi.suppr  ~/Devel/mpi-abi-stubs/lib/libmpi_abi.so /home/devel/mpi/mpich/dev/lib/libmpi_abi.so
Functions changes summary: 0 Removed, 0 Changed, 0 Added (75 filtered out) functions
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable

$ echo $?  # to confirm abidiff succeeds if there is no diff after filtering out MPIX/QMPI functions
0

@hzhou
hzhou merged commit a448ea5 into pmodels:main Nov 11, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants