1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00

Revise the pow(1,inf) IEEE feature test to defeat clever compilers (#184)

Compilers like GCC are capable of optimizing away calls like
pow(1,inf), which caused the IEEE compliance feature test within
libast to incorrectly succeed on platforms with non-IEEE behavior.

This is arguably a bug within GCC, as floating point optimizations
should never alter the behavior of code unless IEEE compliance is
explicitly disabled via a flag like -ffast-math. Programs in which
only some calls to pow are optimized away are liable to severely
malfunction.

Thanks to Martijn Dekker for pointing this issue out and the kind
operators of polarhome.com for permitting me gratis use of their
Unix systems.

src/lib/libast/comp/omitted.c:
- Add IEEE compliant functions that wrap powf, pow, and powl.

src/lib/libast/features/float:
- Look for powf, pow, and powl in the C library.
- For compilers that do the right thing, like the native toolchains
  of Solaris and UnixWare, use lightweight macros to wrap the pow
  functions.
- Use a volatile function pointer through which to access the C
  library's pow function in an attempt to defeat code optimization.
- For these overzealous compilers, define pow to _ast_pow so that
  the same technique can be used within the above functions.
This commit is contained in:
Lev Kujawski 2021-02-18 11:45:27 -07:00 committed by GitHub
parent c2cb0eae19
commit 72968eaed6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 59 additions and 8 deletions

View file

@ -15,6 +15,7 @@ __STDPP__directive pragma pp:hide utime utimes
#include <error.h>
#include <tm.h>
#include "FEATURE/float"
#include "FEATURE/omitted"
#undef OMITTED
@ -1145,6 +1146,36 @@ __EXPORT__ double (*_imp__strtod)(const char*, char**) = strtod;
#endif
/* Kludge to deal with GCC's overzealous optimizer breaking the pow functions.
*
* Removal of this will break IEEE floating point on the SVR4 platforms.
*/
#if _need_ast_pow_funs
# if _lib_powf
float (*volatile _ast_ppowf)(float,float) = &powf;
float _ast_powf(float x, float y)
{
return x == 1.0F ? 1.0F : (*_ast_ppowf)(x,y);
}
# endif
# if _lib_pow
double (*volatile _ast_ppow)(double,double) = &pow;
double _ast_pow(double x, double y)
{
return x == 1.0 ? 1.0 : (*_ast_ppow)(x,y);
}
# endif
# if _lib_powl
long double (*volatile _ast_ppowl)(long double,long double) = &powl;
long double _ast_powl(long double x, long double y)
{
return x == 1.0L ? 1.0L : (*_ast_ppowl)(x,y);
}
# endif
#endif
#ifndef OMITTED
NoN(omitted)