diff options
| author | Paul Eggert | 2018-08-18 20:40:10 -0700 |
|---|---|---|
| committer | Paul Eggert | 2018-08-18 20:41:09 -0700 |
| commit | b1840206ff22359fc099236602928e0fb3828d66 (patch) | |
| tree | dc7a23519474955ed4efcbd975c79c0629a96a2b /src | |
| parent | 6eade1efde873d0b048d8f2841646924cb2ceb16 (diff) | |
| download | emacs-b1840206ff22359fc099236602928e0fb3828d66.tar.gz emacs-b1840206ff22359fc099236602928e0fb3828d66.zip | |
Minor fixups for intmax_t→mpz_t conversion
* src/alloc.c (mpz_set_intmax_slow): Tighten assertion.
Work even in the unlikely case where libgmp uses nails.
* src/data.c (FIXNUMS_FIT_IN_LONG): New constant.
(arith_driver): Use it to tighten compile-time checks.
* src/lisp.h (mpz_set_intmax): Do not assume that converting
an out-of-range value to ‘long’ is harmless, as it might raise
a signal. Use simpler expression; compiler can optimize.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 17 | ||||
| -rw-r--r-- | src/data.c | 9 | ||||
| -rw-r--r-- | src/lisp.h | 11 |
3 files changed, 22 insertions, 15 deletions
diff --git a/src/alloc.c b/src/alloc.c index 60850f73d51..ddc0696ba91 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -3785,18 +3785,21 @@ make_number (mpz_t value) | |||
| 3785 | void | 3785 | void |
| 3786 | mpz_set_intmax_slow (mpz_t result, intmax_t v) | 3786 | mpz_set_intmax_slow (mpz_t result, intmax_t v) |
| 3787 | { | 3787 | { |
| 3788 | /* If long is larger then a faster path is taken. */ | 3788 | /* If V fits in long, a faster path is taken. */ |
| 3789 | eassert (sizeof (intmax_t) > sizeof (long)); | 3789 | eassert (! (LONG_MIN <= v && v <= LONG_MAX)); |
| 3790 | 3790 | ||
| 3791 | bool complement = v < 0; | 3791 | bool complement = v < 0; |
| 3792 | if (complement) | 3792 | if (complement) |
| 3793 | v = -1 - v; | 3793 | v = -1 - v; |
| 3794 | 3794 | ||
| 3795 | /* COUNT = 1 means just a single word of the given size. ORDER = -1 | 3795 | enum { nails = sizeof v * CHAR_BIT - INTMAX_WIDTH }; |
| 3796 | is arbitrary since there's only a single word. ENDIAN = 0 means | 3796 | # ifndef HAVE_GMP |
| 3797 | use the native endian-ness. NAILS = 0 means use the whole | 3797 | /* mini-gmp requires NAILS to be zero, which is true for all |
| 3798 | word. */ | 3798 | likely Emacs platforms. Sanity-check this. */ |
| 3799 | mpz_import (result, 1, -1, sizeof v, 0, 0, &v); | 3799 | verify (nails == 0); |
| 3800 | # endif | ||
| 3801 | |||
| 3802 | mpz_import (result, 1, -1, sizeof v, 0, nails, &v); | ||
| 3800 | if (complement) | 3803 | if (complement) |
| 3801 | mpz_com (result, result); | 3804 | mpz_com (result, result); |
| 3802 | } | 3805 | } |
diff --git a/src/data.c b/src/data.c index 0754d4c176d..7a8179ed38d 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -2775,6 +2775,9 @@ enum arithop | |||
| 2775 | Alogxor | 2775 | Alogxor |
| 2776 | }; | 2776 | }; |
| 2777 | 2777 | ||
| 2778 | enum { FIXNUMS_FIT_IN_LONG = (LONG_MIN <= MOST_NEGATIVE_FIXNUM | ||
| 2779 | && MOST_POSITIVE_FIXNUM <= LONG_MAX) }; | ||
| 2780 | |||
| 2778 | static void | 2781 | static void |
| 2779 | free_mpz_value (void *value_ptr) | 2782 | free_mpz_value (void *value_ptr) |
| 2780 | { | 2783 | { |
| @@ -2829,7 +2832,7 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args) | |||
| 2829 | case Aadd: | 2832 | case Aadd: |
| 2830 | if (BIGNUMP (val)) | 2833 | if (BIGNUMP (val)) |
| 2831 | mpz_add (accum, accum, XBIGNUM (val)->value); | 2834 | mpz_add (accum, accum, XBIGNUM (val)->value); |
| 2832 | else if (sizeof (EMACS_INT) > sizeof (long)) | 2835 | else if (! FIXNUMS_FIT_IN_LONG) |
| 2833 | { | 2836 | { |
| 2834 | mpz_t tem; | 2837 | mpz_t tem; |
| 2835 | mpz_init (tem); | 2838 | mpz_init (tem); |
| @@ -2854,7 +2857,7 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args) | |||
| 2854 | } | 2857 | } |
| 2855 | else if (BIGNUMP (val)) | 2858 | else if (BIGNUMP (val)) |
| 2856 | mpz_sub (accum, accum, XBIGNUM (val)->value); | 2859 | mpz_sub (accum, accum, XBIGNUM (val)->value); |
| 2857 | else if (sizeof (EMACS_INT) > sizeof (long)) | 2860 | else if (! FIXNUMS_FIT_IN_LONG) |
| 2858 | { | 2861 | { |
| 2859 | mpz_t tem; | 2862 | mpz_t tem; |
| 2860 | mpz_init (tem); | 2863 | mpz_init (tem); |
| @@ -2870,7 +2873,7 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args) | |||
| 2870 | case Amult: | 2873 | case Amult: |
| 2871 | if (BIGNUMP (val)) | 2874 | if (BIGNUMP (val)) |
| 2872 | mpz_mul (accum, accum, XBIGNUM (val)->value); | 2875 | mpz_mul (accum, accum, XBIGNUM (val)->value); |
| 2873 | else if (sizeof (EMACS_INT) > sizeof (long)) | 2876 | else if (! FIXNUMS_FIT_IN_LONG) |
| 2874 | { | 2877 | { |
| 2875 | mpz_t tem; | 2878 | mpz_t tem; |
| 2876 | mpz_init (tem); | 2879 | mpz_init (tem); |
diff --git a/src/lisp.h b/src/lisp.h index f2cfe81ca75..fe384d1844b 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -30,10 +30,11 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | |||
| 30 | #include <float.h> | 30 | #include <float.h> |
| 31 | #include <inttypes.h> | 31 | #include <inttypes.h> |
| 32 | #include <limits.h> | 32 | #include <limits.h> |
| 33 | |||
| 33 | #ifdef HAVE_GMP | 34 | #ifdef HAVE_GMP |
| 34 | #include <gmp.h> | 35 | # include <gmp.h> |
| 35 | #else | 36 | #else |
| 36 | #include "mini-gmp.h" | 37 | # include "mini-gmp.h" |
| 37 | #endif | 38 | #endif |
| 38 | 39 | ||
| 39 | #include <intprops.h> | 40 | #include <intprops.h> |
| @@ -3566,10 +3567,10 @@ mpz_set_intmax (mpz_t result, intmax_t v) | |||
| 3566 | /* mpz_set_si works in terms of long, but Emacs may use a wider | 3567 | /* mpz_set_si works in terms of long, but Emacs may use a wider |
| 3567 | integer type, and so sometimes will have to construct the mpz_t | 3568 | integer type, and so sometimes will have to construct the mpz_t |
| 3568 | by hand. */ | 3569 | by hand. */ |
| 3569 | if (sizeof (intmax_t) > sizeof (long) && (long) v != v) | 3570 | if (LONG_MIN <= v && v <= LONG_MAX) |
| 3570 | mpz_set_intmax_slow (result, v); | ||
| 3571 | else | ||
| 3572 | mpz_set_si (result, v); | 3571 | mpz_set_si (result, v); |
| 3572 | else | ||
| 3573 | mpz_set_intmax_slow (result, v); | ||
| 3573 | } | 3574 | } |
| 3574 | 3575 | ||
| 3575 | /* Build a frequently used 2/3/4-integer lists. */ | 3576 | /* Build a frequently used 2/3/4-integer lists. */ |