Lichen

Changeset

879:c77216b79beb
2019-01-26 Paul Boddie raw files shortlog changelog graph Generate floating point exceptions directly from the signal handler. trailing-data
templates/native/float.c (file) templates/progops.c (file) templates/progops.h (file) templates/signals.c (file)
     1.1 --- a/templates/native/float.c	Sat Jan 26 01:04:34 2019 +0100
     1.2 +++ b/templates/native/float.c	Sat Jan 26 21:38:12 2019 +0100
     1.3 @@ -16,8 +16,6 @@
     1.4  this program.  If not, see <http://www.gnu.org/licenses/>.
     1.5  */
     1.6  
     1.7 -#include <setjmp.h>
     1.8 -#include <signal.h>
     1.9  #include <math.h>   /* pow */
    1.10  #include <stdio.h>  /* snprintf */
    1.11  #include <errno.h>  /* errno */
    1.12 @@ -65,29 +63,14 @@
    1.13      return __NULL;
    1.14  }
    1.15  
    1.16 -/* Floating point exception handling. */
    1.17 -
    1.18 -extern jmp_buf __fpe_env;
    1.19 -
    1.20 -/* Floating point operations. */
    1.21 +/* Floating point operations. Exceptions are raised in the signal handler. */
    1.22  
    1.23  __attr __fn_native_float_float_add(__attr __self, __attr self, __attr other)
    1.24  {
    1.25      /* self and other interpreted as float */
    1.26      double i = __TOFLOAT(self);
    1.27      double j = __TOFLOAT(other);
    1.28 -    int signum;
    1.29 -
    1.30 -    /* Perform the operation while handling exceptions. */
    1.31 -    signum = setjmp(__fpe_env);
    1.32 -    if (!signum)
    1.33 -        return __new_float(i + j);
    1.34 -
    1.35 -    /* Exception occurred. */
    1.36 -    if (signum == FPE_FLTOVF)
    1.37 -        __raise_overflow_error();
    1.38 -
    1.39 -    return __NULL;
    1.40 +    return __new_float(i + j);
    1.41  }
    1.42  
    1.43  __attr __fn_native_float_float_sub(__attr __self, __attr self, __attr other)
    1.44 @@ -95,18 +78,7 @@
    1.45      /* self and other interpreted as float */
    1.46      double i = __TOFLOAT(self);
    1.47      double j = __TOFLOAT(other);
    1.48 -    int signum;
    1.49 -
    1.50 -    /* Perform the operation while handling exceptions. */
    1.51 -    signum = setjmp(__fpe_env);
    1.52 -    if (!signum)
    1.53 -        return __new_float(i - j);
    1.54 -
    1.55 -    /* Exception occurred. */
    1.56 -    if (signum == FPE_FLTOVF)
    1.57 -        __raise_overflow_error();
    1.58 -
    1.59 -    return __NULL;
    1.60 +    return __new_float(i - j);
    1.61  }
    1.62  
    1.63  __attr __fn_native_float_float_mul(__attr __self, __attr self, __attr other)
    1.64 @@ -114,20 +86,7 @@
    1.65      /* self and other interpreted as float */
    1.66      double i = __TOFLOAT(self);
    1.67      double j = __TOFLOAT(other);
    1.68 -    int signum;
    1.69 -
    1.70 -    /* Perform the operation while handling exceptions. */
    1.71 -    signum = setjmp(__fpe_env);
    1.72 -    if (!signum)
    1.73 -        return __new_float(i * j);
    1.74 -
    1.75 -    /* Exception occurred. */
    1.76 -    if (signum == FPE_FLTOVF)
    1.77 -        __raise_overflow_error();
    1.78 -    else if (signum == FPE_FLTUND)
    1.79 -        __raise_underflow_error();
    1.80 -
    1.81 -    return __NULL;
    1.82 +    return __new_float(i * j);
    1.83  }
    1.84  
    1.85  __attr __fn_native_float_float_div(__attr __self, __attr self, __attr other)
    1.86 @@ -135,22 +94,7 @@
    1.87      /* self and other interpreted as float */
    1.88      double i = __TOFLOAT(self);
    1.89      double j = __TOFLOAT(other);
    1.90 -    int signum;
    1.91 -
    1.92 -    /* Perform the operation while handling exceptions. */
    1.93 -    signum = setjmp(__fpe_env);
    1.94 -    if (!signum)
    1.95 -        return __new_float(i / j);
    1.96 -
    1.97 -    /* Exception occurred. */
    1.98 -    if (signum == FPE_FLTOVF)
    1.99 -        __raise_overflow_error();
   1.100 -    else if (signum == FPE_FLTUND)
   1.101 -        __raise_underflow_error();
   1.102 -    else if (signum == FPE_FLTDIV)
   1.103 -        __raise_zero_division_error();
   1.104 -
   1.105 -    return __NULL;
   1.106 +    return __new_float(i / j);
   1.107  }
   1.108  
   1.109  __attr __fn_native_float_float_mod(__attr __self, __attr self, __attr other)
   1.110 @@ -158,38 +102,14 @@
   1.111      /* self and other interpreted as float */
   1.112      double i = __TOFLOAT(self);
   1.113      double j = __TOFLOAT(other);
   1.114 -    int signum;
   1.115 -
   1.116 -    /* Perform the operation while handling exceptions. */
   1.117 -    signum = setjmp(__fpe_env);
   1.118 -    if (!signum)
   1.119 -        return __new_float(fmod(i, j));
   1.120 -
   1.121 -    /* Exception occurred. */
   1.122 -    if (signum == FPE_FLTOVF)
   1.123 -        __raise_overflow_error();
   1.124 -    else if (signum == FPE_FLTDIV)
   1.125 -        __raise_zero_division_error();
   1.126 -
   1.127 -    return __NULL;
   1.128 +    return __new_float(fmod(i, j));
   1.129  }
   1.130  
   1.131  __attr __fn_native_float_float_neg(__attr __self, __attr self)
   1.132  {
   1.133      /* self interpreted as float */
   1.134      double i = __TOFLOAT(self);
   1.135 -    int signum;
   1.136 -
   1.137 -    /* Perform the operation while handling exceptions. */
   1.138 -    signum = setjmp(__fpe_env);
   1.139 -    if (!signum)
   1.140 -        return __new_float(-i);
   1.141 -
   1.142 -    /* Exception occurred. */
   1.143 -    if (signum == FPE_FLTOVF)
   1.144 -        __raise_overflow_error();
   1.145 -
   1.146 -    return __NULL;
   1.147 +    return __new_float(-i);
   1.148  }
   1.149  
   1.150  __attr __fn_native_float_float_pow(__attr __self, __attr self, __attr other)
     2.1 --- a/templates/progops.c	Sat Jan 26 01:04:34 2019 +0100
     2.2 +++ b/templates/progops.c	Sat Jan 26 21:38:12 2019 +0100
     2.3 @@ -1,6 +1,6 @@
     2.4  /* Operations depending on program specifics.
     2.5  
     2.6 -Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
     2.7 +Copyright (C) 2015, 2016, 2017, 2018, 2019 Paul Boddie <paul@boddie.org.uk>
     2.8  
     2.9  This program is free software; you can redistribute it and/or modify it under
    2.10  the terms of the GNU General Public License as published by the Free Software
    2.11 @@ -127,6 +127,11 @@
    2.12  #endif /* __HAVE___builtins___exception_io_EOFError */
    2.13  }
    2.14  
    2.15 +void __raise_floating_point_error()
    2.16 +{
    2.17 +    __Raise(__new___builtins___core_FloatingPointError(__NULL));
    2.18 +}
    2.19 +
    2.20  void __raise_io_error(__attr value)
    2.21  {
    2.22  #ifdef __HAVE___builtins___exception_io_IOError
     3.1 --- a/templates/progops.h	Sat Jan 26 01:04:34 2019 +0100
     3.2 +++ b/templates/progops.h	Sat Jan 26 21:38:12 2019 +0100
     3.3 @@ -1,6 +1,6 @@
     3.4  /* Operations depending on program specifics.
     3.5  
     3.6 -Copyright (C) 2015, 2016, 2017, 2018 Paul Boddie <paul@boddie.org.uk>
     3.7 +Copyright (C) 2015, 2016, 2017, 2018, 2019 Paul Boddie <paul@boddie.org.uk>
     3.8  
     3.9  This program is free software; you can redistribute it and/or modify it under
    3.10  the terms of the GNU General Public License as published by the Free Software
    3.11 @@ -48,6 +48,7 @@
    3.12  /* Helpers for raising errors within common operations. */
    3.13  
    3.14  void __raise_eof_error();
    3.15 +void __raise_floating_point_error();
    3.16  void __raise_io_error(__attr value);
    3.17  void __raise_memory_error();
    3.18  void __raise_os_error(__attr value, __attr arg);
     4.1 --- a/templates/signals.c	Sat Jan 26 01:04:34 2019 +0100
     4.2 +++ b/templates/signals.c	Sat Jan 26 21:38:12 2019 +0100
     4.3 @@ -16,11 +16,11 @@
     4.4  this program.  If not, see <http://www.gnu.org/licenses/>.
     4.5  */
     4.6  
     4.7 -#include <setjmp.h>
     4.8  #include <signal.h>
     4.9  #include <stdlib.h>
    4.10  
    4.11  #include "signals.h"
    4.12 +#include "progops.h"
    4.13  
    4.14  void __signals_install_handlers()
    4.15  {
    4.16 @@ -35,11 +35,26 @@
    4.17      sigaction(SIGFPE, &context, NULL);
    4.18  }
    4.19  
    4.20 -jmp_buf __fpe_env;
    4.21 -
    4.22  void __signals_fpe_handler(int signum, siginfo_t *siginfo, void *context)
    4.23  {
    4.24 -    /* Return from setjmp with the signal number. */
    4.25 +    /* Return from setjmp using the signal number. */
    4.26 +
    4.27 +    switch (siginfo->si_code)
    4.28 +    {
    4.29 +        case FPE_FLTOVF:
    4.30 +        __raise_overflow_error();
    4.31 +        break;
    4.32  
    4.33 -    longjmp(__fpe_env, siginfo->si_code);
    4.34 +        case FPE_FLTUND:
    4.35 +        __raise_underflow_error();
    4.36 +        break;
    4.37 +
    4.38 +        case FPE_FLTDIV:
    4.39 +        __raise_zero_division_error();
    4.40 +        break;
    4.41 +
    4.42 +        default:
    4.43 +        __raise_floating_point_error();
    4.44 +        break;
    4.45 +    }
    4.46  }