Possibly ambiguous redefinition of _fpreset()?
Keith Marshall <[email protected]> Wed, 8 Feb 2017 22:30:15 +0000
| Newsgroups | gmane.comp.gnu.mingw.devel |
|---|---|
| Organization | MinGW Project |
| Message-ID | <[email protected]> |
This is a multi-part message in MIME format.
--------------060504060502040700080608
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Guys,
A recent bug report:
https://sourceforge.net/p/mingw/bugs/2326/
prompted me to revisit an idea I've been toying with for a while -- as
it grows bigger, there may be mileage in offering a dynamic linking
option for libmingwex.a. However, when I try to create a DLL, I see:
$ mingw32-gcc -shared -o libmingwex-0.dll -Wl,--whole-archive \
libmingwex.a -Wl,--no-whole-archive -L.
./libmsvcrt.a(dgrcbs00324.o):(.text+0x0): multiple definition
of `_fpreset'
./libmingw32.a(CRT_fp10.o):.../mingwrt/CRT_fp10.c:14: first
defined here
collect2: error: ld returned 1 exit status
The problem here is Danny Smith's stratagem for overriding the default
behaviour of MSVCRT.DLL's _fpreset() function, by shoving an alternative
function of the same name, but with somewhat different behaviour, (which
he implements in CRT_fp10.c), into libmingw32.a, whence it should be
statically linked ahead of -lmsvcrt; he then also provided a further
free-standing implementation, CRT_fp8.c, which attempts to redirect the
call back to the (*_imp__fpreset)() entry point in MSVCRT.DLL.
Am I over-thinking this? Or is this as fragile as it appears? Was
Danny off his game, when he wrote this stuff? I guess it can't be too
serious a problem, since no issues have been reported in the 15 years
or so since Danny wrote it, but I can see the following possibilities:
1) User creates his own DLL, into which CRT_fp10.o is linked, and its
_fpreset() symbol is re-exported; that now provides its own copy of
(*_imp__fpreset)(), which neutralizes Danny's stratagem for calling
the MSVCRT.DLL implementation.
2) User creates his own DLL, within which _fpreset() is called; user
then links this DLL to his main program, which he also links with
CRT_fp8.o; calls to _fpreset() in his DLL will still be resolved
to whichever of CRT_fp10.o or CRT_fp8.o was linked into the DLL
itself, ignoring the intent of linking the main program with
CRT_fp8.o
Given that _fpreset() is strictly a Microsoft concept, conforming to no
known standard, I'd prefer to do away with this ambiguity, and leave it
to MSVCRT.DLL to resolve all references -- users who value standards,
and portability, should be using ISO-C99's fesetenv() function anyway.
Consequently, I've extensively revised Danny's implementation; would
anyone care to review the attached patch, before I commit it?
Of course, if the modified fesetenv() function continues to be linked
statically, from libmingwex.a, the potential for (non-deterministic)
behavioural ambiguity remains, spanning user created DLLs; that could
be mitigated by furnishing libmingwex-0.dll as an alternative to a
statically linked libmingwex.a, so that only a single fesetenv() need
exist within the process address space.
One final related issue: Danny's implementations of both CRT_fp10.c
and CRT_fp8.c defined fpreset(), (without leading underscore), as an
alias for each of his _fpreset() replacement implementations. Given
the complete lack of any defining standard, that seems kind of pointless
to me. Right now I've marked this as deprecated, but have retained a
__LIBIMPL__ stub for it, (reimplemented in terms of fesetenv()), but
it's messy, and I'd just as soon see it disappear altogether.
Any thoughts?
- --
Regards,
Keith.
Public key available from keys.gnupg.net
Key fingerprint: C19E C018 1547 DE50 E1D4 8F53 C0AD 36C6 347E 5A3F
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.20 (GNU/Linux)
iQIcBAEBAgAGBQJYm5v3AAoJEMCtNsY0flo/kMoP/0hMLVflTgbCBHDGxGSUByND
rLZzeA/lD+X2mlB4yNGGVI+VUGFEAbkt20oQYVT9vJiBAHB3+qAUoq3s1/+MJ1gw
9uUQMUKr5yrLTmi1nyR1gAR/zPnpzLwVoMVvVP46oV0skjf8+Ais11/kbHVyTSPy
B4e3WzJWka1f1WSKab+BU1iIzCksCf3OxwANWefHCNxvDBJlR30Hu9cDjbBkf4J5
0Cy4p99OuXQERzlcPplXQG79rrdeHGcH2q5insw8pDNG64Tm7Bbo9Th3JKblyuN+
BiOHHH0b3wPJ/tzJUJt84KBzeAvpv9+7ywzX8bu4Y7wnSneof9sBB/XpG9r8kwG1
+FJRPlHJ9KtMy5wFYka7/GWwmzyMf8vtUxz6awaf46IkPomQZvlLcAMOruvdUu+u
y7hkg4FnAgtGyfIxdQ20LTZjCZ3R5AkNrrpxaHpxU9OHe9TdFk79AL07Sbn+MCh7
iVVdZx+R79rxzbuX1nMJ/YKIYmsZnY1FAJMnmj+5bDzRrgkHf5zAPLYyPnLDJGIy
HHh7PDSrX0TewATDwtCYXB1xOlMKTIPsHjLdHXYla1uXq6syaj9UGn5N0NPh7qsr
RFGQ/thrhkEqWto5MzSEEu0YSlOkLMh6fzZGhLQu7Fy+LpOkZJXtiAHJFoJJrPKK
IwNh8PQbSoDJVLkR5AdT
=M8C7
-----END PGP SIGNATURE-----
--------------060504060502040700080608
Content-Type: text/x-patch;
name="fenv.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="fenv.patch"
# HG changeset patch
# Parent 9a1ff48b35250d65077697acc89a4c270b216f40
Make floating point environment more robust.
* CRT_fp8.c CRT_fp10.c: Delete them; both are replaced by...
* CRT_fenv.c: ...this new common source file; it implements...
(_CRT_fenv): ...this new global variable, with alternative definitions
evaluated during application start-up, to assign one or other of...
[FE_PC53_ENV, FE_PC64_ENV]: ...these, as the preferred default...
[FE_DFL_ENV]: ...represented by this; replacement linkage for...
(_fpreset): ...this MSVCRT.DLL function is no longer supported.
* Makefile.in: Add new static pattern rule, for compiling...
(CRT_fp8.$OBJEXT, CRT_fp10.$OBJEXT): ...each of these, from CRT_env.c
* crt1.c (_gnu_exception_handler, __mingw_CRTStartup): Do not call...
(_fpreset): ...this; its linkage was non-deterministically ambiguous.
(fesetenv): Use this, unambiguously, instead; initially configure the
floating point environment to the predefined state, as assigned to...
[_CRT_fenv]: ...this new global variable; thereafter, reset to...
[FE_DFL_ENV]: ...this ISO-C99 mandatory configuration.
* include/float.h: Assert copyright; tidy layout.
[_MINGW_FLOAT_H_]: Retain, but replace in guard macro usage by...
[_MINGW_FLOAT_H]: ...this, conforming to preferred naming convention.
[_BEGIN_C_DECLS, _END_C_DECLS]: Use them, as appropriate.
(_fpreset): Add _CRTIMP attribute; it is resolved by MSVCRT.DLL
(fpreset): Deprecate it; provide inline __LIBIMPL__ fall-back.
* include/fenv.h: Assert copyright; tidy layout.
[_FENV_H_]: Rename multiple inclusion guard macro, adopting...
[_FENV_H]: ...this preferred stylistic naming convention.
[_BEGIN_C_DECLS, _END_C_DECLS]: Use them, as appropriate.
(FE_INVALID, FE_DENORMAL, FE_DIVBYZERO, FE_OVERFLOW, FE_UNDERFLOW)
(FE_INEXACT, FE_ALL_EXCEPT, FE_TONEAREST, FE_DOWNWARD, FE_UPWARD)
(FE_TOWARDZERO): Redefine them, in terms of enumerated bit positions.
(FE_PD53_ENV, FE_PD64_ENV): New predefined environment selectors; they
serve as initialization-time aliases, causing redefinition of...
[FE_DFL_ENV]: ...this, as run-time alias for one or other of...
[FE_PC53_ENV, FE_PC64_ENV]: ...these, respectively.
* mingwex/fesetenv.c: Assert copyright; tidy layout.
(fesetenv) [FE_PD53_ENV || FE_PD64_ENV]: Handle them, assigning to...
(FE_DFL_ENV): ...this ISO-C99 mandatory configuration, representing...
(fenv_default): ...the value of this new static variable.
(_fpreset): Call it directly; now always resolved by MSVCRT.DLL, so...
(*_imp__fpreset): ...this indirection becomes unnecessary.
diff --git a/mingwrt/CRT_fenv.c b/mingwrt/CRT_fenv.c
new file mode 100644
--- /dev/null
+++ b/mingwrt/CRT_fenv.c
@@ -0,0 +1,63 @@
+/*
+ * CRT_fenv.c
+ *
+ * Specifies the default FPU configuration, in terms of one of the
+ * predefined floating point environments defined in <fenv.h>, via
+ * a global variable assignment, whence the specified selection will
+ * be copied to FE_DFL_ENV at application start-up.
+ *
+ * $Id$
+ *
+ * Written by Keith Marshall <[email protected]>
+ * Copyright (C) 2017, MinGW.org Project.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ *
+ * This file replaces the two original files CRT_fp8.c, and CRT_fp10.c;
+ * compile it using each of the two commands:
+ *
+ * gcc -c -D_CRT_FE_DFL_ENV=8 CRT_fenv.c -o CRT_fp8.o
+ * gcc -c -D_CRT_FE_DFL_ENV=10 CRT_fenv.c -o CRT_fp10.o
+ *
+ * to create the complementary pair of object files, reproducing the
+ * intended effect of the original similarly named object file pair.
+ *
+ */
+#include <fenv.h>
+
+#ifndef _CRT_FE_DFL_ENV
+/* If the user neglects to specify this, assume that the intention is
+ * to reproduce, in FE_DFL_ENV, the effect of the original CRT_fp10.o
+ * object file.
+ */
+# define _CRT_FE_DFL_ENV 10
+#endif
+
+/* Initialize the "_CRT_fenv" global variable, based on compile time
+ * selection, to map FE_DFL_ENV to FE_PC53_env, (precision configured
+ * to 53-bits), or to FE_PC64_ENV, (precision configured to 64-bits),
+ * via initial FPU configuration to FE_PD53_ENV, (precision default
+ * 53-bits), or FE_PD64_ENV, (precision default 64-bits).
+ */
+const fenv_t *_CRT_fenv = (_CRT_FE_DFL_ENV == 8) ? FE_PD53_ENV : FE_PD64_ENV;
+
+/* $RCSfile$: end of file */
diff --git a/mingwrt/CRT_fp10.c b/mingwrt/CRT_fp10.c
deleted file mode 100644
--- a/mingwrt/CRT_fp10.c
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * CRT_FP10.c
- *
- * This defines _fpreset as asm ("fnint"). Calls to _fpreset
- * will set default floating point precesion to 64-bit mantissa
- * at app startup.
- *
- * Linking in CRT_FP10.o before libmingw.a will override the definition
- * set in CRT_FP8.o.
- */
-
-/* Override library _fpreset() with asm fninit */
-void _fpreset (void)
- { __asm__ ( "fninit" ) ;}
-
-#if defined(__PCC__)
-void _Pragma("alias _fpreset") fpreset(void);
-#else
-void __attribute__ ((alias ("_fpreset"))) fpreset(void);
-#endif
diff --git a/mingwrt/CRT_fp8.c b/mingwrt/CRT_fp8.c
deleted file mode 100644
--- a/mingwrt/CRT_fp8.c
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * CRT_FP8.c
- *
- * This forces calls of _fpreset to the MSVCRT function
- * exported from dll. Effectively it make default
- * precison same as apps built with MSVC (53-bit mantissa).
-
- *
- * To change to 64-bit mantissa, link in CRT_FP10.o before libmingw.a.
- */
-
-/* Link against the _fpreset visible in import lib */
-
-extern void (*_imp___fpreset)(void) ;
-void _fpreset (void)
-{ (*_imp___fpreset)(); }
-
-#if defined(__PCC__)
-void _Pragma("alias _fpreset") fpreset(void);
-#else
-void __attribute__ ((alias ("_fpreset"))) fpreset(void);
-#endif
diff --git a/mingwrt/Makefile.in b/mingwrt/Makefile.in
--- a/mingwrt/Makefile.in
+++ b/mingwrt/Makefile.in
@@ -5,11 +5,11 @@
PACKAGE_TARNAME := @PACKAGE_TARNAME@
PACKAGE_VERSION := @PACKAGE_VERSION@
# Written by Keith Marshall <[email protected]>
-# Copyright (C) 2014-2016, MinGW.org Project
+# Copyright (C) 2014-2017, MinGW.org Project
#
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the "Software"),
# to deal in the Software without restriction, including without limitation
@@ -237,15 +237,22 @@ all-deprecated-crt-objects install-depre
vpath %.c ${mingwrt_srcdir}
$(addsuffix .$(OBJEXT), crt1 dllcrt1): %.$(OBJEXT): %.c
$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -D__CRTDLL__ -o $@ $<
# ...while, for the current build case, we need an explicit mapping
-# to identify the disparately named source file.
+# to identify the disparately named source file...
#
$(addsuffix .$(OBJEXT), crt2 dllcrt2): %2.$(OBJEXT): %1.c
$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -o $@ $<
+# ...and for the pair of default FPU configuration selectors, we
+# need to pass the configuration specification to the compiler, when
+# compiling the common source for each of the two cases.
+#
+CRT_fp8.$(OBJEXT) CRT_fp10.$(OBJEXT): CRT_fp%.$(OBJEXT): CRT_fenv.c
+ $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) -D_CRT_FE_DFL_ENV=$* -o $@ $<
+
# The initialization hook for profiling code is inherited from Cygwin,
# where it is built as gcrt0.$(OBJEXT); we build it, unmodified, as each
# of gcrt1.$(OBJEXT) and gcrt2.$(OBJEXT), to satisfy the differing GCC
# specs file dependencies for each of the (deprecated) CRTDLL build
# and (current) MSVCRT build cases, respectively.
diff --git a/mingwrt/crt1.c b/mingwrt/crt1.c
--- a/mingwrt/crt1.c
+++ b/mingwrt/crt1.c
@@ -1,25 +1,48 @@
/*
* crt1.c
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is a part of the mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within the package.
*
- * Source code for the startup proceedures used by all programs. This code
- * is compiled to make crt1.o, which should be located in the library path.
+ * Source code for the startup procedures used by all programs. This
+ * code is compiled to crt1.o, which is located in the library path.
+ *
+ * $Id$
+ *
+ * Written by Colin Peters <[email protected]>
+ * Copyright (C) 1997, 1999, 2002-2007, 2009, 2010, 2014, 2016,
+ * 2017, MinGW.org Project.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*
*/
-
-/* Hide the declaration of _fmode with dllimport attribute in stdlib.h to
- * avoid problems with older GCC.
+#define __IN_MINGW_RUNTIME
+/* Hide the declaration of _fmode(), with its dllimport attribute in
+ * <stdlib.h>, to avoid problems with older GCC.
*/
-#define __IN_MINGW_RUNTIME
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <process.h>
-#include <float.h>
+#include <fenv.h>
+
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <signal.h>
#include "cpu_features.h"
@@ -81,12 +104,11 @@ extern void __getmainargs( int *, char *
*/
extern void __GetMainArgs( int *, char ***, char ***, int );
#endif
void _mingw32_init_mainargs()
-{
- /* This is the old start-up mechanism, in which we use a start-up
+{ /* This is the old start-up mechanism, in which we use a start-up
* hook provided by Microsoft's runtime library to initialize the
* argument and environment vectors.
*
* Note that the preferred method for accessing the environment
* vector is via a direct pointer retrieved from the runtime DLL,
@@ -96,21 +118,21 @@ void _mingw32_init_mainargs()
*/
char **dummy_envp;
# define _CRT_GLOB_OPT _CRT_glob & __CRT_GLOB_USE_MSVCRT__
# ifdef __MSVCRT__
- /* The MSVCRT.DLL start-up hook requires this invocation
- * protocol...
- */
- _startupinfo start_info = { 0 };
- __getmainargs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT, &start_info );
+ /* The MSVCRT.DLL start-up hook requires this invocation
+ * protocol...
+ */
+ _startupinfo start_info = { 0 };
+ __getmainargs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT, &start_info );
# else
- /* ...while a somewhat simpler protocol is applicable, in
- * the case of the CRTDLL.DLL version.
- */
- __GetMainArgs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT );
+ /* ...while a somewhat simpler protocol is applicable, in
+ * the case of the CRTDLL.DLL version.
+ */
+ __GetMainArgs( &_argc, &_argv, &dummy_envp, _CRT_GLOB_OPT );
# endif
}
/* TLS initialization hook.
*/
@@ -136,20 +158,19 @@ extern const PIMAGE_TLS_CALLBACK __dyn_t
extern int _fmode;
#ifdef __MSVCRT__
extern int* __p__fmode(void); /* To access the dll _fmode */
#endif
-/*
- * Setup the default file handles to have the _CRT_fmode mode, as well as
- * any new files created by the user.
+/* Setup the default file handles to have the _CRT_fmode mode,
+ * as well as any new files created by the user.
*/
extern int _CRT_fmode;
static void
_mingw32_init_fmode (void)
-{
- /* Don't set the std file mode if the user hasn't set any value for it.
+{ /* Don't set the std file mode if the user hasn't set any
+ * value for it.
*/
if (_CRT_fmode)
{
_fmode = _CRT_fmode;
@@ -165,13 +186,13 @@ static void
}
/* Now sync the dll _fmode to the one for this .exe.
*/
# ifdef __MSVCRT__
- *__p__fmode() = _fmode;
+ *__p__fmode() = _fmode;
# else
- *_imp___fmode_dll = _fmode;
+ *_imp___fmode_dll = _fmode;
# endif
}
/* This function will be called when a trap occurs. Thanks to
* Jacob Navia for this contribution.
@@ -182,46 +203,50 @@ static CALLBACK long
void (*old_handler) (int);
long action = EXCEPTION_CONTINUE_SEARCH;
int reset_fpu = 0;
switch (exception_data->ExceptionRecord->ExceptionCode)
- {
+ {
case EXCEPTION_ACCESS_VIOLATION:
- /* test if the user has set SIGSEGV */
+ /* Test if the user has set SIGSEGV
+ */
old_handler = signal (SIGSEGV, SIG_DFL);
if (old_handler == SIG_IGN)
- {
- /* this is undefined if the signal was raised by anything other
- than raise (). */
- signal (SIGSEGV, SIG_IGN);
- action = EXCEPTION_CONTINUE_EXECUTION;
- }
+ { /* This is undefined if the signal was raised by
+ * anything other than raise()
+ */
+ signal (SIGSEGV, SIG_IGN);
+ action = EXCEPTION_CONTINUE_EXECUTION;
+ }
else if (old_handler != SIG_DFL)
- {
- /* This means 'old' is a user defined function. Call it */
- (*old_handler) (SIGSEGV);
- action = EXCEPTION_CONTINUE_EXECUTION;
- }
+ { /* This means 'old_handler' is a user defined
+ * function. Call it
+ */
+ (*old_handler) (SIGSEGV);
+ action = EXCEPTION_CONTINUE_EXECUTION;
+ }
break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
case EXCEPTION_PRIV_INSTRUCTION:
- /* test if the user has set SIGILL */
+ /* Test if the user has set SIGILL
+ */
old_handler = signal (SIGILL, SIG_DFL);
if (old_handler == SIG_IGN)
- {
- /* this is undefined if the signal was raised by anything other
- than raise (). */
- signal (SIGILL, SIG_IGN);
- action = EXCEPTION_CONTINUE_EXECUTION;
- }
+ { /* This is undefined if the signal was raised by
+ * anything other than raise()
+ */
+ signal (SIGILL, SIG_IGN);
+ action = EXCEPTION_CONTINUE_EXECUTION;
+ }
else if (old_handler != SIG_DFL)
- {
- /* This means 'old' is a user defined function. Call it */
- (*old_handler) (SIGILL);
- action = EXCEPTION_CONTINUE_EXECUTION;
- }
+ { /* This means 'old_handler' is a user defined
+ * function. Call it
+ */
+ (*old_handler) (SIGILL);
+ action = EXCEPTION_CONTINUE_EXECUTION;
+ }
break;
case EXCEPTION_FLT_INVALID_OPERATION:
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_FLT_DENORMAL_OPERAND:
@@ -230,37 +255,61 @@ static CALLBACK long
case EXCEPTION_FLT_INEXACT_RESULT:
reset_fpu = 1;
/* fall through. */
case EXCEPTION_INT_DIVIDE_BY_ZERO:
- /* test if the user has set SIGFPE */
+ /* Test if the user has set SIGFPE
+ */
old_handler = signal (SIGFPE, SIG_DFL);
if (old_handler == SIG_IGN)
- {
- signal (SIGFPE, SIG_IGN);
- if (reset_fpu)
- _fpreset ();
- action = EXCEPTION_CONTINUE_EXECUTION;
- }
+ {
+ signal (SIGFPE, SIG_IGN);
+ if (reset_fpu)
+ fesetenv (FE_DFL_ENV);
+ action = EXCEPTION_CONTINUE_EXECUTION;
+ }
else if (old_handler != SIG_DFL)
- {
- /* This means 'old' is a user defined function. Call it */
- (*old_handler) (SIGFPE);
- action = EXCEPTION_CONTINUE_EXECUTION;
- }
- break;
-
- default:
- break;
- }
+ { /* This means 'old_handler' is a user defined
+ * function. Call it
+ */
+ (*old_handler) (SIGFPE);
+ action = EXCEPTION_CONTINUE_EXECUTION;
+ }
+ }
return action;
}
-/* The function mainCRTStartup is the entry point for all console programs.
+/* During application start-up, we establish the default configuration
+ * for the FPU. MSVCRT.DLL provides the _fpreset() function to perform
+ * the appropriate initialization, but it sets the default operation to
+ * be in IEEE-754 8-byte mode, whereas we prefer IEEE-754 10-byte mode,
+ * to better support GCC's 10-byte long doubles; nevertheless, we offer
+ * the option, via the _CRT_fenv global variable, to establish either
+ * one of these modes as initial default, it should be set to either
+ * FE_PD64_ENV, (defined in <fenv.h>, reflecting the 64-bit precision
+ * of the 10-byte mode, and established as default for _CRT_fenv within
+ * the runtime library), or overridden by a setting of FE_PD53_ENV, in
+ * user code, like this:
+ *
+ * #include <fenv.h>
+ * const fenv_t *_CRT_fenv = FE_PD53_ENV;
+ *
+ * (or by linking with CRT_fp8.o), to select the 53-bit precision of
+ * the 8-byte mode.
+ *
+ * Whichever of these assignments, i.e. FE_PD64_ENV or FE_PD53_ENV, is
+ * in effect when the following __mingw_CRTStartup() function is invoked,
+ * will cause FE_DFL_ENV to be mapped to one or other of the predefined
+ * environments, FE_PC64_ENV or FE_PC53_ENV, respectively.
*/
-static void __MINGW_ATTRIB_NORETURN
-__mingw_CRTStartup (void)
+extern const fenv_t *_CRT_fenv;
+
+/* The function mainCRTStartup(), (defined below), is the entry point
+ * for all console programs, it is, primarily, a wrapper around the
+ * following __mingw_CRTStartup() helper function.
+ */
+static __MINGW_ATTRIB_NORETURN void __mingw_CRTStartup (void)
{
int nRet;
/* Initialize TLS callback.
*/
@@ -272,23 +321,22 @@ static void __MINGW_ATTRIB_NORETURN
* Win32 SE is not 1-to-1, so caveat emptor.
*
*/
SetUnhandledExceptionFilter (_gnu_exception_handler);
- /* Initialize floating point unit.
+ /* Initialize the floating point unit.
*/
- __cpu_features_init (); /* Do we have SSE, etc.*/
- _fpreset (); /* Supplied by the runtime library. */
+ __cpu_features_init (); /* Do we have SSE, etc. */
+ fesetenv (_CRT_fenv); /* Supplied by the runtime library. */
/* Set up __argc, __argv and _environ.
*/
_setargv ();
- /* Sets the default file mode.
- * If _CRT_fmode is set, also set mode for stdin, stdout
- * and stderr, as well
- * NOTE: DLLs don't do this because that would be rude!
+ /* Set the default file mode. If _CRT_fmode is set, also set mode
+ * for stdin, stdout and stderr, as well. NOTE: DLLs don't do this
+ * because that would be rude!
*/
_mingw32_init_fmode ();
/* Adust references to dllimported data that have non-zero offsets.
*/
@@ -297,47 +345,47 @@ static void __MINGW_ATTRIB_NORETURN
/* Align the stack to 16 bytes for the sake of SSE ops in main
* or in functions inlined into main.
*/
asm __volatile__ ("andl $-16, %%esp" : : : "%esp");
- /* From libgcc.a, __main calls global class constructors via
- __do_global_ctors, This in turn registers __do_global_dtors
- as the first entry of the app's atexit table. We do this
- explicitly at app startup rather than rely on gcc to generate
- the call in main's prologue, since main may be imported from a dll
- which has its own __do_global_ctors. */
- __main ();
+ /* From libgcc.a, __main() calls global class constructors via
+ * __do_global_ctors(); this in turn registers __do_global_dtors()
+ * as the first entry of the application's atexit() table. We do
+ * this explicitly at application startup rather than rely on GCC
+ * to generate the call in main()'s prologue, since main() may be
+ * imported from a DLL which has its own __do_global_ctors()
+ */
+ __main ();
- /* Call the main function. If the user does not supply one
+ /* Call the main() function. If the user does not supply one
* the one in the 'libmingw32.a' library will be linked in, and
- * that one calls WinMain. See main.c in the 'lib' dir
+ * that one calls WinMain(). See main.c in the 'lib' directory
* for more details.
*/
nRet = main (_argc, _argv, environ);
- /* Perform exit processing for the C library. This means
- * flushing output and calling 'atexit' registered functions.
+ /* Perform exit processing for the C library. This means flushing
+ * output and calling atexit() registered functions.
*/
_cexit ();
ExitProcess (nRet);
}
-/*
- * The function mainCRTStartup is the entry point for all console programs.
+/* The function mainCRTStartup() is the entry point for all console
+ * programs.
*/
void
mainCRTStartup (void)
{
#ifdef __MSVCRT__
__set_app_type (__CONSOLE_APP);
#endif
__mingw_CRTStartup ();
}
-/*
- * For now the GUI startup function is the same as the console one.
+/* For now the GUI startup function is the same as the console one.
* This simply gets rid of the annoying warning about not being able
* to find WinMainCRTStartup when linking GUI applications.
*/
void
WinMainCRTStartup (void)
@@ -346,22 +394,17 @@ WinMainCRTStartup (void)
__set_app_type (__GUI_APP);
#endif
__mingw_CRTStartup ();
}
-/*
- * We force use of library version of atexit, which is only
- * visible in import lib as _imp__atexit
+/* We force use of library version of atexit(), which is only
+ * visible in import lib as _imp__atexit
*/
extern int (*_imp__atexit)(void (*)(void));
-int atexit (void (* pfn )(void) )
-{
- return ( (*_imp__atexit)(pfn));
-}
+int atexit (void (* pfn )(void)){ return (*_imp__atexit)(pfn); }
-/* Likewise for non-ANSI _onexit */
+/* Likewise for non-ANSI _onexit()
+ */
extern _onexit_t (*_imp___onexit)(_onexit_t);
-_onexit_t
-_onexit (_onexit_t pfn )
-{
- return (*_imp___onexit)(pfn);
-}
+_onexit_t _onexit (_onexit_t pfn){ return (*_imp___onexit)(pfn); }
+
+/* $RCSfile$: end of file */
diff --git a/mingwrt/include/fenv.h b/mingwrt/include/fenv.h
--- a/mingwrt/include/fenv.h
+++ b/mingwrt/include/fenv.h
@@ -1,107 +1,197 @@
-#ifndef _FENV_H_
-#define _FENV_H_
+/*
+ * fenv.h
+ *
+ * Structures and constants defining, and functions for management of,
+ * the floating point environment.
+ *
+ * $Id$
+ *
+ * Written by Danny Smith <[email protected]>
+ * Copyright (C) 2002, 2003, 2005-2007, 2017, MinGW.org Project
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef _FENV_H
+#pragma GCC system_header
+#define _FENV_H
+/* All MinGW headers are required to include <_mingw.h>
+ */
#include <_mingw.h>
-/* FPU status word exception flags */
-#define FE_INVALID 0x01
-#define FE_DENORMAL 0x02
-#define FE_DIVBYZERO 0x04
-#define FE_OVERFLOW 0x08
-#define FE_UNDERFLOW 0x10
-#define FE_INEXACT 0x20
-#define FE_ALL_EXCEPT (FE_INVALID | FE_DENORMAL | FE_DIVBYZERO \
- | FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
+/* FPU status word flags indicating exceptions. Each is represented
+ * by a single bit, sequentially and contiguously assigned to the low
+ * order bits of the status word, enumerated from lowest:
+ */
+enum
+{ __FE_INVALID_EXCEPT_FLAG_SHIFT,
+ __FE_DENORMAL_EXCEPT_FLAG_SHIFT,
+ __FE_DIVBYZERO_EXCEPT_FLAG_SHIFT,
+ __FE_OVERFLOW_EXCEPT_FLAG_SHIFT,
+ __FE_UNDERFLOW_EXCEPT_FLAG_SHIFT,
+ __FE_INEXACT_EXCEPT_FLAG_SHIFT,
-/* FPU control word rounding flags */
-#define FE_TONEAREST 0x0000
-#define FE_DOWNWARD 0x0400
-#define FE_UPWARD 0x0800
-#define FE_TOWARDZERO 0x0c00
+ /* The final entry in the shift enumeration represents the order
+ * of the rightmost bit which does NOT represent an exception flag;
+ * we use it as a high water mark, for generation of the aggregate
+ * mask for ALL exception flags; arithmetically, this becomes the
+ * numeric value of a pseudo-flag placed at the high water mark,
+ * less one.
+ */
+ __FE_ALL_EXCEPT_HWM_SHIFT
+# define FE_ALL_EXCEPT ((0x01 << __FE_ALL_EXCEPT_HWM_SHIFT) - 1)
+};
-/* The MXCSR exception flags are the same as the
- FE flags. */
-#define __MXCSR_EXCEPT_FLAG_SHIFT 0
+#define __FE_EXCEPT(__NAME__) (0x01 << __FE_##__NAME__##_EXCEPT_FLAG_SHIFT)
-/* How much to shift FE status word exception flags
- to get the MXCSR exeptions masks, */
-#define __MXCSR_EXCEPT_MASK_SHIFT 7
+#define FE_INVALID __FE_EXCEPT(INVALID)
+#define FE_DENORMAL __FE_EXCEPT(DENORMAL)
+#define FE_DIVBYZERO __FE_EXCEPT(DIVBYZERO)
+#define FE_OVERFLOW __FE_EXCEPT(OVERFLOW)
+#define FE_UNDERFLOW __FE_EXCEPT(UNDERFLOW)
+#define FE_INEXACT __FE_EXCEPT(INEXACT)
-/* How much to shift FE control word rounding flags
- to get MXCSR rounding flags, */
-#define __MXCSR_ROUND_FLAG_SHIFT 3
+/* FPU control word flags to specify rounding mode; this may be
+ * represented as a selection from a four-way enumeration...
+ */
+enum
+{ __FE_ROUND_TONEAREST,
+ __FE_ROUND_DOWNWARD,
+ __FE_ROUND_UPWARD,
+ __FE_ROUND_TOWARDZERO
+};
+/* ...with the actual flag bits offset 10-bits from the rightmost
+ * bit in the control word; hence, the rounding mode macros become:
+ */
+#define __FE_ROUND(__MODE__) (__FE_ROUND_##__MODE__ << 10)
+
+#define FE_TONEAREST __FE_ROUND(TONEAREST)
+#define FE_DOWNWARD __FE_ROUND(DOWNWARD)
+#define FE_UPWARD __FE_ROUND(UPWARD)
+#define FE_TOWARDZERO __FE_ROUND(TOWARDZERO)
+
+/* The MXCSR exception flags are the same as those for the FPU...
+ */
+#define __MXCSR_EXCEPT_FLAG_SHIFT 0
+
+/* ...and the corresponding mask bits are offset by a further 7-bit
+ * shift to the left...
+ */
+#define __MXCSR_EXCEPT_MASK_SHIFT 7
+
+/* ...while the MXCSR rounding mode flags adopt the same enumeration,
+ * but are offset a further 3-bits to the left of those representing
+ * the FPU rounding mode selection flags.
+ */
+#define __MXCSR_ROUND_FLAG_SHIFT 3
#ifndef RC_INVOKED
-/*
- For now, support only for the basic abstraction of flags that are
- either set or clear. fexcept_t could be structure that holds more
- info about the fp environment.
-*/
+/* For now, support only for the basic abstraction of flags that are
+ * either set or clear; fexcept_t could be a structure that holds more
+ * info about the fp environment.
+ */
typedef unsigned short fexcept_t;
-/* This 32-byte struct represents the entire floating point
- environment as stored by fnstenv or fstenv, augmented by
- the contents of the MXCSR register, as stored by stmxcsr
- (if CPU supports it). */
-typedef struct
-{
- unsigned short __control_word;
- unsigned short __unused0;
- unsigned short __status_word;
- unsigned short __unused1;
- unsigned short __tag_word;
- unsigned short __unused2;
- unsigned int __ip_offset; /* instruction pointer offset */
- unsigned short __ip_selector;
- unsigned short __opcode;
- unsigned int __data_offset;
- unsigned short __data_selector;
- unsigned short __unused3;
- unsigned int __mxcsr; /* contents of the MXCSR register */
+typedef struct __fenv_t
+{ /* This 28-byte structure represents the entire floating point
+ * environment of the FPU, as stored by either the "fnstenv", or
+ * the "fstenv" instruction.
+ */
+ unsigned short __control_word;
+ unsigned short __unused0;
+ unsigned short __status_word;
+ unsigned short __unused1;
+ unsigned short __tag_word;
+ unsigned short __unused2;
+ unsigned int __ip_offset; /* instruction pointer offset */
+ unsigned short __ip_selector;
+ unsigned short __opcode;
+ unsigned int __data_offset;
+ unsigned short __data_selector;
+ unsigned short __unused3;
+
+ /* The structure is extended, beyond the 28 byte requirement to
+ * store the FPU state, by 4 additional bytes, which then makes it
+ * sufficient to also store the contents of the MXCSR register, as
+ * stored by the "stmxcsr" instruction, (if the CPU supports it).
+ */
+ unsigned int __mxcsr; /* content of the MXCSR register */
} fenv_t;
+/* The ISO-C99 standard, section 7.6 paragraph 8 requires us to define
+ * the FE_DFL_ENV macro; it specifies restoration of the FPU environment
+ * to its default state, as established at application start-up.
+ */
+#define FE_DFL_ENV ((const fenv_t *)(0))
-/*The C99 standard (7.6.9) allows us to define implementation-specific macros for
- different fp environments */
+/* Paragraph 9 of the same section of ISO-C99 provides for the definition
+ * of implementation-specific macros to identify alternative predefined
+ * FPU environment configuration; we exploit this licence to offer:
+ *
+ * FP_PC64_ENV -- Intel standard 80-bit (64-bit precision); this is
+ * consistent with IEEE-754 extended precision, and
+ * the configuration preferred by MinGW, because it
+ * matches the format of GCC's 80-bit long doubles.
+ *
+ * FP_PC53_ENV -- IEEE-754 64-bit (53-bit precision); consistent
+ * with Microsoft's preferred FPU configuration;
+ * (they offer no better than 64-bit long doubles).
+ */
+#define FE_PC64_ENV ((const fenv_t *)(-1))
+#define FE_PC53_ENV ((const fenv_t *)(-2))
-/* The default Intel x87 floating point environment (64-bit mantissa) */
-#define FE_PC64_ENV ((const fenv_t *)-1)
+/* The following pair of additional predefined environment macros serve
+ * as aliases for the preceding pair, respectively, with the added side
+ * effect that, when passed to fesetenv(), each causes its respective
+ * alias to become associated with FE_DFL_ENV in subsequent calls.
+ */
+#define FE_PD64_ENV ((const fenv_t *)(-3))
+#define FE_PD53_ENV ((const fenv_t *)(-4))
-/* The floating point environment set by MSVCRT _fpreset (53-bit mantissa) */
-#define FE_PC53_ENV ((const fenv_t *)-2)
-
-/* The FE_DFL_ENV macro is required by standard.
- fesetenv will use the environment set at app startup.*/
-#define FE_DFL_ENV ((const fenv_t *) 0)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
+_BEGIN_C_DECLS
/*TODO: Some of these could be inlined */
-/* 7.6.2 Exception */
-extern int __cdecl __MINGW_NOTHROW feclearexcept (int);
-extern int __cdecl __MINGW_NOTHROW fegetexceptflag (fexcept_t * flagp, int excepts);
-extern int __cdecl __MINGW_NOTHROW feraiseexcept (int excepts );
-extern int __cdecl __MINGW_NOTHROW fesetexceptflag (const fexcept_t *, int);
-extern int __cdecl __MINGW_NOTHROW fetestexcept (int excepts);
+/* ISO-C99 section 7.6.2 -- Floating Point Exception Handling
+ */
+extern __cdecl __MINGW_NOTHROW int feclearexcept (int);
+extern __cdecl __MINGW_NOTHROW int fegetexceptflag (fexcept_t *, int);
+extern __cdecl __MINGW_NOTHROW int feraiseexcept (int);
+extern __cdecl __MINGW_NOTHROW int fesetexceptflag (const fexcept_t *, int);
+extern __cdecl __MINGW_NOTHROW int fetestexcept (int);
-/* 7.6.3 Rounding */
+/* ISO-C99 section 7.6.3 -- Floating Point Rounding Mode Control
+ */
+extern __cdecl __MINGW_NOTHROW int fegetround (void);
+extern __cdecl __MINGW_NOTHROW int fesetround (int);
-extern int __cdecl __MINGW_NOTHROW fegetround (void);
-extern int __cdecl __MINGW_NOTHROW fesetround (int mode);
+/* ISO-C99 section 7.6.4 -- Floating Point Environment Configuration
+ */
+extern __cdecl __MINGW_NOTHROW int fegetenv (fenv_t *);
+extern __cdecl __MINGW_NOTHROW int fesetenv (const fenv_t *);
+extern __cdecl __MINGW_NOTHROW int feupdateenv (const fenv_t *);
+extern __cdecl __MINGW_NOTHROW int feholdexcept (fenv_t *);
-/* 7.6.4 Environment */
+_END_C_DECLS
-extern int __cdecl __MINGW_NOTHROW fegetenv (fenv_t * envp);
-extern int __cdecl __MINGW_NOTHROW fesetenv (const fenv_t * );
-extern int __cdecl __MINGW_NOTHROW feupdateenv (const fenv_t *);
-extern int __cdecl __MINGW_NOTHROW feholdexcept (fenv_t *);
-
-#ifdef __cplusplus
-}
-#endif
-#endif /* Not RC_INVOKED */
-
-#endif /* ndef _FENV_H */
+#endif /* ! RC_INVOKED */
+#endif /* !_FENV_H: $RCSfile$: end of file */
diff --git a/mingwrt/include/float.h b/mingwrt/include/float.h
--- a/mingwrt/include/float.h
+++ b/mingwrt/include/float.h
@@ -1,169 +1,227 @@
-#ifndef _MINGW_FLOAT_H_
/*
* float.h
*
- * This file has no copyright assigned and is placed in the Public Domain.
- * This file is a part of the mingw-runtime package.
- * No warranty is given; refer to the file DISCLAIMER within the package.
+ * Constants related to floating point arithmetic. Also included here are
+ * some non-ANSI mechanisms for accessing the floating point controller.
*
- * Constants related to floating point arithmetic.
+ * $Id$
*
- * Also included here are some non-ANSI bits for accessing the floating
- * point controller.
+ * Written by Colin Peters <[email protected]>
+ * Copyright (C) 1997, 1999-2005, 2007, 2010, 2011, 2017, MinGW.org Project
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
*
*/
-#define _MINGW_FLOAT_H_
+#ifndef _MINGW_FLOAT_H
+#pragma GCC system_header
+#define _MINGW_FLOAT_H
/*
* NOTE:
*
* GCC provides float.h, but it doesn't include the non-standard stuff for
* accessing the fp controller. We parse the GCC-supplied header, for its
* standard content, and then define the MS-specific extensions here.
*
* In a MinGW standard Win32 hosted environment, this should be the float.h
* found by a system include path search, but this can't be guaranteed; for
* a cross-compiler setup, the GCC-supplied header, which is guarded by the
- * _FLOAT_H___ macro, may be found first, thus...
+ * _FLOAT_H___ macro, may be found first, thus, except when compiling any
+ * __LIBIMPL__ stub...
*
*/
#if !defined(_FLOAT_H___) && !defined(__FLOAT_H)
-
- /*
- * ...when we didn't find the GCC-supplied header first, we want to pull
+ /* ...when we didn't find the GCC-supplied header first, we want to pull
* it in now; include_next should achieve this, (and we must rely on the
* GCC header maintainers to extend us the same courtesy, to get this one
* pulled in, when the GCC-supplied header is found first).
- *
*/
-# include_next <float.h>
+# define _MINGW_FLOAT_H_ 1 /* GCC's <float.h> needs to see this */
+# include_next <float.h> /* !__CRT_ALIAS __LIBIMPL__( FUNCTION = fpreset ) */
#endif
-/* All the headers include this file. */
+/* All MinGW headers are required to include <_mingw.h>
+ */
#include <_mingw.h>
-/*
- * Functions and definitions for controlling the FPU.
+/* Functions and definitions for controlling the FPU.
*/
-#ifndef __STRICT_ANSI__
+#ifndef __STRICT_ANSI__
/* TODO: These constants are only valid for x86 machines */
-/* Control word masks for unMask */
-#define _MCW_EM 0x0008001F /* Error masks */
-#define _MCW_IC 0x00040000 /* Infinity */
-#define _MCW_RC 0x00000300 /* Rounding */
-#define _MCW_PC 0x00030000 /* Precision */
+/* Control word masks for unMask
+ */
+#define _MCW_EM 0x0008001F /* Error masks */
+#define _MCW_IC 0x00040000 /* Infinity */
+#define _MCW_RC 0x00000300 /* Rounding */
+#define _MCW_PC 0x00030000 /* Precision */
-/* Control word values for unNew (use with related unMask above) */
-#define _EM_INVALID 0x00000010
-#define _EM_DENORMAL 0x00080000
-#define _EM_ZERODIVIDE 0x00000008
-#define _EM_OVERFLOW 0x00000004
-#define _EM_UNDERFLOW 0x00000002
-#define _EM_INEXACT 0x00000001
-#define _IC_AFFINE 0x00040000
-#define _IC_PROJECTIVE 0x00000000
-#define _RC_CHOP 0x00000300
-#define _RC_UP 0x00000200
-#define _RC_DOWN 0x00000100
-#define _RC_NEAR 0x00000000
-#define _PC_24 0x00020000
-#define _PC_53 0x00010000
-#define _PC_64 0x00000000
+/* Control word values for unNew (use with related unMask above)
+ */
+#define _EM_INVALID 0x00000010
+#define _EM_DENORMAL 0x00080000
+#define _EM_ZERODIVIDE 0x00000008
+#define _EM_OVERFLOW 0x00000004
+#define _EM_UNDERFLOW 0x00000002
+#define _EM_INEXACT 0x00000001
+#define _IC_AFFINE 0x00040000
+#define _IC_PROJECTIVE 0x00000000
+#define _RC_CHOP 0x00000300
+#define _RC_UP 0x00000200
+#define _RC_DOWN 0x00000100
+#define _RC_NEAR 0x00000000
+#define _PC_24 0x00020000
+#define _PC_53 0x00010000
+#define _PC_64 0x00000000
-/* These are also defined in Mingw math.h, needed to work around
- GCC build issues. */
-/* Return values for fpclass. */
#ifndef __MINGW_FPCLASS_DEFINED
-#define __MINGW_FPCLASS_DEFINED 1
-#define _FPCLASS_SNAN 0x0001 /* Signaling "Not a Number" */
-#define _FPCLASS_QNAN 0x0002 /* Quiet "Not a Number" */
-#define _FPCLASS_NINF 0x0004 /* Negative Infinity */
-#define _FPCLASS_NN 0x0008 /* Negative Normal */
-#define _FPCLASS_ND 0x0010 /* Negative Denormal */
-#define _FPCLASS_NZ 0x0020 /* Negative Zero */
-#define _FPCLASS_PZ 0x0040 /* Positive Zero */
-#define _FPCLASS_PD 0x0080 /* Positive Denormal */
-#define _FPCLASS_PN 0x0100 /* Positive Normal */
-#define _FPCLASS_PINF 0x0200 /* Positive Infinity */
+#define __MINGW_FPCLASS_DEFINED 1
+/* These are also defined in MinGW <math.h>; these duplicates are
+ * needed here, to work around GCC build issues. FIXME: we should
+ * be able to factor this, at least to avoid any potential for the
+ * introduction of inconsistent definitions.
+ *
+ *
+ * Return values for fpclass.
+ */
+#define _FPCLASS_SNAN 0x0001 /* Signaling "Not a Number" */
+#define _FPCLASS_QNAN 0x0002 /* Quiet "Not a Number" */
+#define _FPCLASS_NINF 0x0004 /* Negative Infinity */
+#define _FPCLASS_NN 0x0008 /* Negative Normal */
+#define _FPCLASS_ND 0x0010 /* Negative Denormal */
+#define _FPCLASS_NZ 0x0020 /* Negative Zero */
+#define _FPCLASS_PZ 0x0040 /* Positive Zero */
+#define _FPCLASS_PD 0x0080 /* Positive Denormal */
+#define _FPCLASS_PN 0x0100 /* Positive Normal */
+#define _FPCLASS_PINF 0x0200 /* Positive Infinity */
+
#endif /* __MINGW_FPCLASS_DEFINED */
-/* invalid subconditions (_SW_INVALID also set) */
-#define _SW_UNEMULATED 0x0040 /* unemulated instruction */
-#define _SW_SQRTNEG 0x0080 /* square root of a neg number */
-#define _SW_STACKOVERFLOW 0x0200 /* FP stack overflow */
-#define _SW_STACKUNDERFLOW 0x0400 /* FP stack underflow */
+/* Invalid subconditions (_SW_INVALID also set)
+ */
+#define _SW_UNEMULATED 0x0040 /* unemulated instruction */
+#define _SW_SQRTNEG 0x0080 /* square root of a neg number */
+#define _SW_STACKOVERFLOW 0x0200 /* FP stack overflow */
+#define _SW_STACKUNDERFLOW 0x0400 /* FP stack underflow */
-/* Floating point error signals and return codes */
-#define _FPE_INVALID 0x81
-#define _FPE_DENORMAL 0x82
-#define _FPE_ZERODIVIDE 0x83
-#define _FPE_OVERFLOW 0x84
-#define _FPE_UNDERFLOW 0x85
-#define _FPE_INEXACT 0x86
-#define _FPE_UNEMULATED 0x87
-#define _FPE_SQRTNEG 0x88
-#define _FPE_STACKOVERFLOW 0x8a
-#define _FPE_STACKUNDERFLOW 0x8b
-#define _FPE_EXPLICITGEN 0x8c /* raise( SIGFPE ); */
+/* Floating point error signals and return codes
+ */
+#define _FPE_INVALID 0x81
+#define _FPE_DENORMAL 0x82
+#define _FPE_ZERODIVIDE 0x83
+#define _FPE_OVERFLOW 0x84
+#define _FPE_UNDERFLOW 0x85
+#define _FPE_INEXACT 0x86
+#define _FPE_UNEMULATED 0x87
+#define _FPE_SQRTNEG 0x88
+#define _FPE_STACKOVERFLOW 0x8A
+#define _FPE_STACKUNDERFLOW 0x8B
+#define _FPE_EXPLICITGEN 0x8C /* raise SIGFPE */
#ifndef RC_INVOKED
-#ifdef __cplusplus
-extern "C" {
-#endif
+_BEGIN_C_DECLS
/* Set the FPU control word as cw = (cw & ~unMask) | (unNew & unMask),
* i.e. change the bits in unMask to have the values they have in unNew,
- * leaving other bits unchanged. */
-_CRTIMP unsigned int __cdecl __MINGW_NOTHROW _controlfp (unsigned int unNew, unsigned int unMask);
-_CRTIMP unsigned int __cdecl __MINGW_NOTHROW _control87 (unsigned int unNew, unsigned int unMask);
+ * leaving other bits unchanged.
+ */
+_CRTIMP __cdecl __MINGW_NOTHROW unsigned int _controlfp (unsigned int unNew, unsigned int unMask);
+_CRTIMP __cdecl __MINGW_NOTHROW unsigned int _control87 (unsigned int unNew, unsigned int unMask);
+#define _clear87 _clearfp
+#define _status87 _statusfp
-_CRTIMP unsigned int __cdecl __MINGW_NOTHROW _clearfp (void); /* Clear the FPU status word */
-_CRTIMP unsigned int __cdecl __MINGW_NOTHROW _statusfp (void); /* Report the FPU status word */
-#define _clear87 _clearfp
-#define _status87 _statusfp
+_CRTIMP __cdecl __MINGW_NOTHROW unsigned int _clearfp (void); /* Clear the FPU status word */
+_CRTIMP __cdecl __MINGW_NOTHROW unsigned int _statusfp (void); /* Report the FPU status word */
-/*
- MSVCRT.dll _fpreset initializes the control register to 0x27f,
- the status register to zero and the tag word to 0FFFFh.
- This differs from asm instruction finit/fninit which set control
- word to 0x37f (64 bit mantissa precison rather than 53 bit).
- By default, the mingw version of _fpreset sets fp control as
- per fninit. To use the MSVCRT.dll _fpreset, include CRT_fp8.o when
- building your application.
-*/
-void __cdecl __MINGW_NOTHROW _fpreset (void);
-void __cdecl __MINGW_NOTHROW fpreset (void);
+/* MSVCRT.DLL provides _fpreset() to initialize the FPU; it initializes
+ * the control register to 0x27F, (thus selecting 53-bit precision), the
+ * status register to zero and the tag word to 0FFFFh. This differs from
+ * Intel's default configuration, (as established by the asm instructions
+ * "finit" and "fninit"), which set the control word to 0x37F, (yielding
+ * 64-bit precison rather than 53-bit).
+ *
+ * Nominally, MinGW prefers to configure the FPU for 64-bit precision, as
+ * that is a better fit for support of GCC's 10-byte long doubles. This
+ * was formerly achieved by provision of an alternative implementation of
+ * _fpreset(), intended to be statically linked into MinGW applications,
+ * (with variants enabling 64-bit precision by default, or alternatively,
+ * when the application is explicitly linked with CRT_fp8.o, providing
+ * 53-bit precision instead). Unfortunately, this linking strategy may
+ * lead to non-deterministic ambiguity over which _fpreset() variant is
+ * called, in the event of the call originating in any user implemented,
+ * or third party DLL. Consequently, support for this strategy has been
+ * withdrawn. _fpreset() now ALWAYS refers to the MSVCRT.DLL function,
+ * (and thus ALWAYS selects 53-bit precision); MinGW applications should
+ * now use the ISO-C99 standard fesetenv() function to configure the FPU,
+ * (as the start-up code now does, to enable 64-bit precision by default,
+ * but continuing to support linking with CRT_fp8.o, to initialize the
+ * configuration to 53-bit precision).
+ */
+_CRTIMP __cdecl __MINGW_NOTHROW void _fpreset (void);
-/* Global 'variable' for the current floating point error code. */
-_CRTIMP int * __cdecl __MINGW_NOTHROW __fpecode(void);
-#define _fpecode (*(__fpecode()))
+/* Former MinGW releases also provided fpreset(), implemented as an alias
+ * for _fpreset(), (in whichever guise it was deployed); deprecate this,
+ * but retain the association for backward compatibility, (noting that it
+ * will now redirect the call to fesetenv(), as recommended above, with
+ * the configuration selection set to FE_DFL_ENV).
+ */
+__cdecl __MINGW_NOTHROW void fpreset (void) __MINGW_ATTRIB_DEPRECATED;
-/*
- * IEEE recommended functions. MS puts them in float.h
+#ifndef __NO_INLINE__
+/* Provide the implementation of fpreset() as an inline stub; for this,
+ * we need to expose a minimal opaque subset of <fenv.h>, and we assume
+ * that FE_DFL_ENV is equivalent to (const fenv_t *)(0), (as it is, in
+ * the MinGW implementation of <fenv.h>).
+ */
+typedef struct __fenv_t fenv_t;
+__cdecl __MINGW_NOTHROW int fesetenv (const fenv_t *);
+
+__CRT_ALIAS __LIBIMPL__( FUNCTION = fpreset )
+void fpreset (void){ fesetenv ((const fenv_t *)(0)); }
+#endif
+
+/* Global 'variable' for the current floating point error code.
+ */
+#define _fpecode (*(__fpecode()))
+_CRTIMP __cdecl __MINGW_NOTHROW int *__fpecode (void);
+
+/* IEEE recommended functions. Microsoft puts them in <float.h>,
* but they really belong in math.h.
*/
+_CRTIMP __cdecl __MINGW_NOTHROW double _chgsign (double);
+_CRTIMP __cdecl __MINGW_NOTHROW double _copysign (double, double);
+_CRTIMP __cdecl __MINGW_NOTHROW double _logb (double);
+_CRTIMP __cdecl __MINGW_NOTHROW double _nextafter (double, double);
+_CRTIMP __cdecl __MINGW_NOTHROW double _scalb (double, long);
-_CRTIMP double __cdecl __MINGW_NOTHROW _chgsign (double);
-_CRTIMP double __cdecl __MINGW_NOTHROW _copysign (double, double);
-_CRTIMP double __cdecl __MINGW_NOTHROW _logb (double);
-_CRTIMP double __cdecl __MINGW_NOTHROW _nextafter (double, double);
-_CRTIMP double __cdecl __MINGW_NOTHROW _scalb (double, long);
+_CRTIMP __cdecl __MINGW_NOTHROW int _finite (double);
+_CRTIMP __cdecl __MINGW_NOTHROW int _fpclass (double);
+_CRTIMP __cdecl __MINGW_NOTHROW int _isnan (double);
-_CRTIMP int __cdecl __MINGW_NOTHROW _finite (double);
-_CRTIMP int __cdecl __MINGW_NOTHROW _fpclass (double);
-_CRTIMP int __cdecl __MINGW_NOTHROW _isnan (double);
+_END_C_DECLS
-#ifdef __cplusplus
-}
-#endif
+#endif /* ! RC_INVOKED */
+#endif /* !__STRICT_ANSI__ */
-#endif /* Not RC_INVOKED */
-
-#endif /* Not __STRICT_ANSI__ */
-
-#endif /* _MINGW_FLOAT_H_ */
-
+#endif /* _MINGW_FLOAT_H: $RCSfile$: end of file */
diff --git a/mingwrt/mingwex/fesetenv.c b/mingwrt/mingwex/fesetenv.c
--- a/mingwrt/mingwex/fesetenv.c
+++ b/mingwrt/mingwex/fesetenv.c
@@ -1,57 +1,130 @@
+/*
+ * fesetenv.c
+ *
+ * Implements the fesetenv(3) function, per ISO-C99 section 7.6.4.3
+ *
+ * $Id$
+ *
+ * Written by Danny Smith <[email protected]>
+ * Copyright (C) 2002, 2005, 2006, 2017, MinGW.org Project.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice, this permission notice, and the following
+ * disclaimer shall be included in all copies or substantial portions of
+ * the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+#define __USE_CRTIMP
+
#include <fenv.h>
#include <float.h>
#include "cpu_features.h"
-/* 7.6.4.3
- The fesetenv function establishes the floating-point environment
- represented by the object pointed to by envp. The argument envp
- points to an object set by a call to fegetenv or feholdexcept, or
- equal the macro FE_DFL_ENV or an implementation-defined environment
- macro. Note that fesetenv merely installs the state of the exception
- flags represented through its argument, and does not raise these
- exceptions.
- */
+int fesetenv( const fenv_t *fenvp )
+{
+ /* Specified by ISO-C99 section 7.6.4.3
+ *
+ * The fesetenv() function establishes the floating-point environment
+ * represented by the object pointed to by "envp". The argument "envp"
+ * points to an object set by a call to fegetenv() or feholdexcept(), or
+ * equals the macro, FE_DFL_ENV, or an implementation-defined environment
+ * macro. Note that fesetenv() merely sets the state of the exception
+ * flags represented through its argument; it does not raise these
+ * exceptions.
+ *
+ *
+ * The following static variable stores the predefined environment
+ * which is associated with FE_DFL_ENV; initialize it to represent
+ * the Intel X87 default configuration.
+ */
+ static const fenv_t *fenv_default = FE_PC64_ENV;
-extern void (*_imp___fpreset)( void ) ;
+ /* Before anything else, establish a default exception handling
+ * policy for SSE instructions, to be used in conjunction with the
+ * predefined FPU state macros, (establishing an effective default
+ * MXCSR status value of 0x1F80, so masking all exceptions, while
+ * leaving all other bits as zero), in the event that SSE support
+ * is available.
+ */
+ unsigned fenv_mxcsr = FE_ALL_EXCEPT << __MXCSR_EXCEPT_MASK_SHIFT;
-int fesetenv (const fenv_t * envp)
-{
- /* Default mxcsr status is to mask all exceptions. All other bits
- are zero. */
+ if( fenvp == FE_PD64_ENV )
+ /* This is a request to both initialize the FPU state, to the
+ * FE_PC64_ENV predefined state, and to store that state as the
+ * application default.
+ */
+ fenvp = fenv_default = FE_PC64_ENV;
- unsigned int _csr = FE_ALL_EXCEPT << __MXCSR_EXCEPT_MASK_SHIFT /*= 0x1f80 */;
+ else if( fenvp == FE_PD53_ENV )
+ /* Conversely, this requests initialization of FPU state to the
+ * FE_PC53_ENV predefined state, and to store that state as the
+ * new application default.
+ */
+ fenvp = fenv_default = FE_PC53_ENV;
- if (envp == FE_PC64_ENV)
- /*
- * fninit initializes the control register to 0x37f,
- * the status register to zero and the tag word to 0FFFFh.
- * The other registers are unaffected.
- */
- __asm__ ("fninit");
+ else if( fenvp == FE_DFL_ENV )
+ /* This simply requests initialization of FPU state to whichever
+ * of the two preceding predefined states has been previously set
+ * as the application default.
+ */
+ fenvp = fenv_default;
- else if (envp == FE_PC53_ENV)
- /*
- * MS _fpreset() does same *except* it sets control word
- * to 0x27f (53-bit precison).
- * We force calling _fpreset in msvcrt.dll
- */
+ if( fenvp == FE_PC64_ENV )
+ /* The FPU's "fninit" instruction initializes the FPU control
+ * word register to 0x37F, the status register to zero and the
+ * tag word to 0xFFFF. The other registers are unaffected.
+ */
+ __asm__( "fninit" );
- (*_imp___fpreset)();
-
- else if (envp == FE_DFL_ENV)
- /* Use the choice made at app startup */
+ else if( fenvp == FE_PC53_ENV )
+ /* Microsoft's _fpreset() does the same, EXCEPT that it sets
+ * the control word to 0x27F (53-bit precison). Here, we want
+ * to force a call to _fpreset() in MSVCRT.DLL
+ */
_fpreset();
else
- {
- __asm__ ("fldenv %0;" : : "m" (*envp));
- /* Setting the reserved high order bits of MXCSR causes a segfault */
- _csr = envp ->__mxcsr & 0xffff;
- }
+ { /* The requested FPU state is not represented by any of the
+ * predefined state macros; assume it is a properly constructed
+ * fenv_t structure, and load it to the FPU as is.
+ */
+ __asm__( "fldenv %0" :: "m" (*fenvp) );
- /* Set MXCSR */
- if (__HAS_SSE)
- __asm__ volatile ("ldmxcsr %0" : : "m" (_csr));
+ /* Also, in the event that SSE instructions may be supported,
+ * extract the MXCSR flags from this same structure, to be used
+ * instead of the defaults which have been established for use
+ * in conjunction with the predefined state macros, noting that
+ * attempting to set any of the reserved high-order flags will
+ * induce a segmentation fault, so mask them off.
+ */
+ fenv_mxcsr = fenvp->__mxcsr & 0xFFFF;
+ }
+ if( __HAS_SSE )
+ /* Finally, if SSE instructions are supported, set the MXCSR
+ * exception handling policy flags...
+ */
+ __asm__( "ldmxcsr %0" :: "m" (fenv_mxcsr) );
+
+ /* ...and we are done; there is no mechanism for us to detect
+ * failure, so simply return zero, indicating success.
+ */
return 0;
}
+
+/* $RCSfile$: end of file */
--------------060504060502040700080608
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, SlashDot.org! http://sdm.link/slashdot
--------------060504060502040700080608
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
MinGW-dvlpr mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-dvlpr
--------------060504060502040700080608--