From 4e81043908471848eef2b16db1791cf005b90c1c Mon Sep 17 00:00:00 2001 From: jjgarcia Date: Wed, 26 Oct 2005 09:14:59 +0000 Subject: [PATCH] Insert FWAIT routines in make_{short,long}float to detect floating point exceptions under x86 --- src/CHANGELOG | 4 ++-- src/aclocal.m4 | 19 +++++++++++++++++++ src/c/arch/fpe_none.c | 26 ++++++++++++++++++++++++++ src/c/arch/fpe_x86.c | 25 +++++++++++++++++++++++++ src/c/number.d | 18 ++++++++++++++---- src/configure | 19 ++++++++++++++++++- src/configure.in | 1 + src/h/config.h.in | 2 ++ 8 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 src/c/arch/fpe_none.c create mode 100644 src/c/arch/fpe_x86.c diff --git a/src/CHANGELOG b/src/CHANGELOG index b27de4364..4ee1224a1 100644 --- a/src/CHANGELOG +++ b/src/CHANGELOG @@ -67,9 +67,9 @@ ECL 0.9h applications must be compiled and linked against ECL so that the appropiate replacements for pthread_create()/CreateThread() are used. - - On systems with GNU libc, we are able to signal and trap floating point + - On some systems we are able to signal and trap floating point exceptions of the following kinds: overflow, underflow and division by zero. - Trapping of these exceptions can be disabled with (SI::TRAP-FPE NIL). In + Trapping of these exceptions can be disabled with (SI::TRAP-FPE T NIL). In practice this means overflows in routines like EXP, EXPT, etc, are now detected. diff --git a/src/aclocal.m4 b/src/aclocal.m4 index 6fb7122fc..7b513b6a2 100644 --- a/src/aclocal.m4 +++ b/src/aclocal.m4 @@ -531,3 +531,22 @@ AC_TRY_COMPILE(,[static __thread void *data;], dnl We deactivate this test because it seems to slow down ECL A LOT!!! ac_cv_ecl___thread=no ]) + +dnl ---------------------------------------------------------------------- +dnl Choose the type of code to detect floating point exceptions and +dnl raise them. +dnl +AC_DEFUN([ECL_FPE_MODEL], +[AC_MSG_CHECKING([for code to detect FP exceptions]) +case "${host_cpu}" in + i686 |i586 | pentium* | athlon* ) + ECL_FPE_CODE="${srcdir}/c/arch/fpe_x86.c" + AC_MSG_RESULT([x86]) + ;; + *) + ECL_FPE_CODE="${srcdir}/c/arch/fpe_none.c" + AC_MSG_RESULT([not available]) + ;; +esac +AC_SUBST(ECL_FPE_CODE) +]) \ No newline at end of file diff --git a/src/c/arch/fpe_none.c b/src/c/arch/fpe_none.c new file mode 100644 index 000000000..cde52ed87 --- /dev/null +++ b/src/c/arch/fpe_none.c @@ -0,0 +1,26 @@ +/* + fpe_none.c -- Nonportable component of the floating point code (dummy) +*/ +/* + Copyright (c) 2005, Juan Jose Garcia Ripoll. + + ECL is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + See file '../Copyright' for full details. +*/ + +/* + * The ecl_detect_fpe() is a macro (or a function) that detects whether a + * floating point exception has been produced in a recent time. Currently + * it is of great importance in the x86 architecture because exceptions + * are not signaled on the instruction that originates the problem, but on + * the next FP instruction. However, we could conceivably write a more + * complex code on architectures that do not signal FP exceptions by + * checking the control word of the FPU and doing the dispatching ourselves + * instead of using signal(). + */ + +#define ecl_detect_fpe() (void)0 diff --git a/src/c/arch/fpe_x86.c b/src/c/arch/fpe_x86.c new file mode 100644 index 000000000..00a5eb9a9 --- /dev/null +++ b/src/c/arch/fpe_x86.c @@ -0,0 +1,25 @@ +/* + fpe_x86.c -- Nonportable component of the floating point code +*/ +/* + Copyright (c) 2005, Juan Jose Garcia Ripoll. + + ECL is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + See file '../Copyright' for full details. +*/ + +/* + * See fpe_none.c for a description + */ + +#ifdef _MSVC +#define ecl_detect_fpe() __asm fwait +#endif + +#ifdef __GNUC__ +#define ecl_detect_fpe() asm("fwait") +#endif diff --git a/src/c/number.d b/src/c/number.d index 6ead62462..0f2cdfca1 100644 --- a/src/c/number.d +++ b/src/c/number.d @@ -136,10 +136,15 @@ make_shortfloat(float f) { cl_object x; + ecl_detect_fpe(); if (f == (float)0.0) return(cl_core.shortfloat_zero); - if (isnanf(f) || !finite(f)) - FEerror("Not a number.",0); + if (isnanf(f)) { + cl_error(1, @'division-by-zero'); + } + if (!finite(f)) { + cl_error(1, @'floating-point-overflow'); + } x = cl_alloc_object(t_shortfloat); sf(x) = f; return(x); @@ -150,10 +155,15 @@ make_longfloat(double f) { cl_object x; + ecl_detect_fpe(); if (f == (double)0.0) return(cl_core.longfloat_zero); - if (isnan(f) || !finite(f)) - FEerror("Not a number.",0); + if (isnan(f)) { + cl_error(1, @'division-by-zero'); + } + if (!finite(f)) { + cl_error(1, @'floating-point-overflow'); + } x = cl_alloc_object(t_longfloat); lf(x) = f; return(x); diff --git a/src/configure b/src/configure index 5d3b7a2a6..0466ff756 100755 --- a/src/configure +++ b/src/configure @@ -310,7 +310,7 @@ ac_includes_default="\ # include #endif" -ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS docdir buildir ECL_CFLAGS FASL_LIBS CORE_LIBS SHARED_LDFLAGS BUNDLE_LDFLAGS SHORT_SITE_NAME LONG_SITE_NAME EXTRA_OBJS TARGETS SUBDIRS LIBRARIES LSP_LIBRARIES LSP_FEATURES build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX CPP RANLIB ac_ct_RANLIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE true_srcdir true_builddir CP RM MV EXE_SUFFIX ARCHITECTURE SOFTWARE_TYPE SOFTWARE_VERSION MACHINE_INSTANCE MACHINE_VERSION LDRPATH LIBPREFIX LIBEXT SHAREDEXT SHAREDPREFIX INSTALL_TARGET thehost INFOEXT INSTALL_INFO EGREP ECL_SETJMP ECL_LONGJMP ECL_FILE_CNT CL_FIXNUM_TYPE CL_FIXNUM_BITS CL_FIXNUM_MAX CL_FIXNUM_MIN LIBOBJS POW_LIB ECL_CC CLX_INFO LTLIBOBJS' +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS docdir buildir ECL_CFLAGS FASL_LIBS CORE_LIBS SHARED_LDFLAGS BUNDLE_LDFLAGS SHORT_SITE_NAME LONG_SITE_NAME EXTRA_OBJS TARGETS SUBDIRS LIBRARIES LSP_LIBRARIES LSP_FEATURES build build_cpu build_vendor build_os host host_cpu host_vendor host_os CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT CXX CXXFLAGS ac_ct_CXX CPP RANLIB ac_ct_RANLIB INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA LN_S SET_MAKE true_srcdir true_builddir CP RM MV EXE_SUFFIX ARCHITECTURE SOFTWARE_TYPE SOFTWARE_VERSION MACHINE_INSTANCE MACHINE_VERSION LDRPATH LIBPREFIX LIBEXT SHAREDEXT SHAREDPREFIX INSTALL_TARGET thehost INFOEXT INSTALL_INFO EGREP ECL_SETJMP ECL_LONGJMP ECL_FILE_CNT ECL_FPE_CODE CL_FIXNUM_TYPE CL_FIXNUM_BITS CL_FIXNUM_MAX CL_FIXNUM_MIN LIBOBJS POW_LIB ECL_CC CLX_INFO LTLIBOBJS' ac_subst_files='' # Initialize some variables set by options. @@ -6881,6 +6881,22 @@ _ACEOF fi +echo "$as_me:$LINENO: checking for code to detect FP exceptions" >&5 +echo $ECHO_N "checking for code to detect FP exceptions... $ECHO_C" >&6 +case "${host_cpu}" in + i686 |i586 | pentium* | athlon* ) + ECL_FPE_CODE="${srcdir}/c/arch/fpe_x86.c" + echo "$as_me:$LINENO: result: x86" >&5 +echo "${ECHO_T}x86" >&6 + ;; + *) + ECL_FPE_CODE="${srcdir}/c/arch/fpe_none.c" + echo "$as_me:$LINENO: result: not available" >&5 +echo "${ECHO_T}not available" >&6 + ;; +esac + + echo "$as_me:$LINENO: checking whether stack growns downwards" >&5 @@ -10498,6 +10514,7 @@ s,@EGREP@,$EGREP,;t t s,@ECL_SETJMP@,$ECL_SETJMP,;t t s,@ECL_LONGJMP@,$ECL_LONGJMP,;t t s,@ECL_FILE_CNT@,$ECL_FILE_CNT,;t t +s,@ECL_FPE_CODE@,$ECL_FPE_CODE,;t t s,@CL_FIXNUM_TYPE@,$CL_FIXNUM_TYPE,;t t s,@CL_FIXNUM_BITS@,$CL_FIXNUM_BITS,;t t s,@CL_FIXNUM_MAX@,$CL_FIXNUM_MAX,;t t diff --git a/src/configure.in b/src/configure.in index 0a7ba3955..d566195cf 100644 --- a/src/configure.in +++ b/src/configure.in @@ -338,6 +338,7 @@ ECL_LINEFEED_MODE ECL_FIND_SETJMP ECL_FILE_STRUCTURE ECL_FFI +ECL_FPE_MODEL dnl ----------------------------------------------------------------------- dnl Study the call conventions diff --git a/src/h/config.h.in b/src/h/config.h.in index 93547dc01..0f4d81e0b 100644 --- a/src/h/config.h.in +++ b/src/h/config.h.in @@ -275,3 +275,5 @@ typedef unsigned @CL_FIXNUM_TYPE@ cl_hashkey; #endif /* MSDOS */ #define ECL_ARCHITECTURE "@ARCHITECTURE@" + +#include "@ECL_FPE_CODE@"