Bug: GMP 4.2.1 will not build as x86 fat binary

librik@panix.com librik at panix.com
Tue May 16 05:17:42 CEST 2006

GMP 4.2.1 will not build as an x86 fat binary.  It is missing the
functions mpn_add_nc and mpn_sub_nc, which mpn/generic/addsub_n.c

The "fat mpn" mechanism does not make mpn_add_nc() and mpn_sub_nc()
available, although mpn_add_n() and mpn_sub_n() are provided.

(Each of the CPU-specific *_add_n.asm/*_sub_n.asm files does provide
its own version of mpn_add_nc and mpn_sub_nc, but the fat.c system
doesn't pick them up and use them to make a "master" mpn_add_nc or
mpn_sub_nc.  They're not in the CPUVEC.  I don't know why not.)

The new GMP 4.2.1 file mpn/addsub_n.c requires mpn_add_nc() and
mpn_sub_nc() in numerous places.  See, for example, line 61:

#if HAVE_NATIVE_mpn_add_nc || !HAVE_NATIVE_mpn_add_n
          acyo = mpn_add_nc (r1p + off, s1p + off, s2p + off, this_n, acyo);
          acyn = mpn_add_n (r1p + off, s1p + off, s2p + off, this_n);
          acyo = acyn + mpn_add_1 (r1p + off, r1p + off, this_n, acyo);

When a "fat binary" is built, almost none of the HAVE_NATIVE macros
are defined in config.h:

/* Define to 1 each of the following for which a native (ie. CPU specific)
    implementation of the corresponding routine exists.  */
/* #undef HAVE_NATIVE_mpn_add_n */
/* #undef HAVE_NATIVE_mpn_add_nc */
.... etc. etc. ...

Since "HAVE_NATIVE_mpn_add_n" is not defined, the mpn_add_nc line
in addsub_n.c is used.  But since the fat binary doesn't provide
any function mpn_add_nc(), this is an unresolved external.  The
same is true of mpn_sub_nc().

I first ran into this while building a shared library (DLL) for
Windows, since DLLs will not link with unresolved external
references.  But this is a general bug for all x86 platforms,
and I was able to reproduce the situation on Linux:

    ../configure --enable-shared --disable-static --enable-fat
    cd mpn/.libs
    nm libmpn.a | grep add_nc
       00000000 T __gmpn_add_nc_x86
       00000000 T __gmpn_add_nc_k6
       00000000 T __gmpn_add_nc_k7
       00000000 T __gmpn_add_nc_pentium
       00000000 T __gmpn_add_nc_p6
       00000000 T __gmpn_add_nc_pentium4_sse2
                U __gmpn_add_nc

The only reference to __gmpn_add_nc is an unresolved external.
The library still links, but that's just because Linux delays
resolution until later, when the library is loaded.  When you
link to an application that pulls in mpn_addsub_n(), you'll
get an unresolved external symbol error for __gmpn_add_nc and

There are two possible fixes I see for this:

(1) Add mpn_add_nc and mpn_sub_nc to the list of functions made
    available by fat.c.  This means adding it to the CPUVEC.
    (I think this is the right thing to do, because why should a
    GMP operation available in every x86 CPU-specific binary not
    be available in the x86 "fat binary"?)

    However, this requires changes in fat.c, x86-defs.m4, and
    something complicated inside configure.  It's a bit beyond
    my expertise, unfortunately.

(2) Rewrite addsub_n.c so it uses mpn_add_n() and mpn_sub_n()
    exclusively, not relying on mpn_add_nc() or mpn_sub_nc().

- David Librik
librik at panix.com

More information about the gmp-bugs mailing list