On 2012-11-11 14:07, Bruce Evans wrote:
On Sat, 10 Nov 2012, Dimitry Andric wrote:
On 2012-11-10 22:43, Konstantin Belousov wrote:
On Sat, Nov 10, 2012 at 09:22:10PM +0000, Dimitry Andric wrote:
...
Author: dim
Date: Sat Nov 10 21:22:10 2012
New Revision: 242879
URL: http://svnweb.freebsd.org/changeset/base/242879
Log:
Only define isnan, isnanf, __isnan and __isnanf in libc.so, not in
libc.a and libc_p.a. In addition, define isnan in libm.a and libm_p.a,
but not in libm.so.
This makes it possible to statically link executables using both isnan
and isnanf with libc and libm.
...
So you broke ABI for libm ?
No, both libc.so and libm.so are the same as before. Only the .a files
are changed.
I should probably have made the commit message more clear, sorry about
that.
Hopefully "fixed" instead of "broke" (except the .so files are unchanged
so they are still broken). I use the hack of ifdefing out the definition
of __isnanf() in libm. isnan() is already ifdefed out there. I didn't
touch the compatibility cruft weak references to isnanf() there -- libc
has it too, so it is not needed any more than isnan() here.
The pessimality of these functions is another problem. C99 only requires
the isnan() API, and only requires it to be a macro. gcc-4.2.1 and clang
(but not gcc-3.3.3 which I often test with) provide good builtins for
these functions. But the FreeBSD implementation destroys use of the
builtins with some help from the ABI:
- if you compile isnan*(x) calls using gcc _without_ including <math.h>,
then everything works right -- they builtins are used and are optimal
- if you compile isnan*(x) calls using gcc _without_ including <math.h>,
then you get annoying (and broken) warnings about implicit function
declarations being invalid in C99. This is a bug in clang. These
functions are reserved in C99, so some other warning for them would
be correct, but things warning is wrong in several ways:
- implicit function declarations are not invalid in C9
Implicit function declarations are invalid in C99, not in C89. Clang
defaults to C99. Whether the function is reserved or not, should not
matter.
- the same warning is printed for -ffreestanding, but these functions
are not reserved by C99 then.
Again, I don't agree. Reserved or not is not relevant. If the above
reasoning was followed, we would never have to include <stdio.h> either,
because all those prototypes would already be implicitly there? :-)
After turning off the broken warning using
-Wno-implicit-function-declarations, everything works right for these
function calls, but of course not for others for which you want this
warning.
So for clang you must include <math.h> for calling these functions,
No, according to the C99 standard you must include <math.h>. Quoting
7.12.3.4:
Synopsis:
#include <math.h>
int isnan(real-floating x);
The synopses of all math functions explicitly have the the #include at
the top.
and
of course for other FP library features, omitting the include is even
more impractical. This gives the pessimizations:
- the isnan() macro translates to isnan() for doubles, __isnanf() for
floats and __isnanfl() for long doubles. The null translation for
doubles gives the builtin and it works as above, but the other
translations give the library functions with their underscored
spelling. Compilers don't understand this spelling, so they don't
give the builtins. So isnan() is pessimized when applied to floats
and long doubles.
Yes, this is rather unfortunate. Though I originally assumed that the
libm authors found all the compiler builtins inferior in some way, and
therefore supplied their own implementations. :-)
OTOH, if you forget that isnan() is type-generic and spell it isnanf()
or isnanl(), then the float and long double cases mostly work right
again:
- same behaviour if <math.h> is not included (and -O is used)
- if <math.h> is included, then it declares isnanf() but not isnanl(),
since only the former is compatibility cruft and has an extern function.
So isnanf() always works and the builtin is always used with -O and
and the extern function is used without -O. But isnanl() causes the
following problems:
- -Wimplicit* warning
- linkage failure without -O.
Another problem is that the extern __isnanl() is broken on x86, but the
builtin works. The extern functions do bit tests that are rather slow
but not slow enough to be correct (they don't check for pseudo-numbers
which the hardware treats as NaNs), but the builtin does a simple x != x
test which is probably optimal, and works.
Similarly for some other macros (they convert to spelling that compilers
don't understand, and at least the classification macros are broken on
psudo-numbers, but now the broken cases are mostly ones for which the
builtins don't exist or is broken).
In short, maybe just:
#define isnan __builtin_isnan
? That should cover all cases. With a fallback for !gcc && !clang,
obviously. The functions stay behind for backwards compatibility.
Fixing the pessimizations would reduce the ABI problems. Both libc
and libm should translate to the builtin if it exists and is a real
builtin (not a libcall). This seems reasonable even without -O, since
C99 doesn't require any functions to exist so nothing should take their
addresses or try to call them as non-macros ('(isnan)(x)'). <math.h>
already has complications to use builtins for 1 set of interfaces only.
The only problems are that it is that it is hard to tell if builtins
exist and are real (there are compiler predefines for the set that
uses builtins but not for most sets).
How is it hard to tell? Both gcc and clang support those builtins,
unless you want to support very old versions of gcc, which might not
have them.
With this, the library functions are never used by new compiles and
are only needed by old applications. All static copies of them can
be removed, but the .so ones are still needed until the ABI is changed.
When will the library isnanf() have been deprecated long enough to
remove in .so's too? Maybe it never needed to be preserved, since
old applications will link to old libraries that have it.
I don't think we can ever remove them from libc.so anymore, unless
version bumps are reintroduced. :-)
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"