diff options
| author | Paul Eggert | 2018-08-21 02:16:50 -0700 |
|---|---|---|
| committer | Paul Eggert | 2018-08-21 02:38:53 -0700 |
| commit | d6a497dd887cdbb35c5b4e2929e83962ba708159 (patch) | |
| tree | 9f0441f9fe88419b71e568b05ef7f7bea0a0ff06 /src | |
| parent | 77fc2725985b4e5ef977ae6930835c7f0771c61c (diff) | |
| download | emacs-d6a497dd887cdbb35c5b4e2929e83962ba708159.tar.gz emacs-d6a497dd887cdbb35c5b4e2929e83962ba708159.zip | |
Avoid libgmp aborts by imposing limits
libgmp calls ‘abort’ when given numbers too big for its
internal data structures. The numeric limit is large and
platform-dependent; with 64-bit GMP 6.1.2 it is around
2**2**37. Work around the problem by refusing to call libgmp
functions with arguments that would cause an abort. With luck
libgmp will have a better way to do this in the future.
Also, introduce a variable integer-width that lets the user
control how large bignums can be. This currently defaults
to 2**16, i.e., it allows bignums up to 2**2**16. This
should be enough for ordinary computation, and should
help Emacs to avoid thrashing or hanging.
Problem noted by Pip Cet (Bug#32463#71).
* doc/lispref/numbers.texi, etc/NEWS:
Document recent bignum changes, including this one.
Improve documentation for bitwise operations, in the light
of bignums.
* src/alloc.c (make_number): Enforce integer-width.
(integer_overflow): New function.
(xrealloc_for_gmp, xfree_for_gmp):
Move here from emacs.c, as it's memory allocation.
(init_alloc): Initialize GMP here, rather than in emacs.c.
(integer_width): New var.
* src/data.c (GMP_NLIMBS_MAX, NLIMBS_LIMIT): New constants.
(emacs_mpz_size, emacs_mpz_mul)
(emacs_mpz_mul_2exp, emacs_mpz_pow_ui): New functions.
(arith_driver, Fash, expt_integer): Use them.
(expt_integer): New function, containing integer code
that was out of place in floatfns.c.
(check_bignum_size, xmalloc_for_gmp): Remove.
* src/emacs.c (main): Do not initialize GMP here.
* src/floatfns.c (Fexpt): Use expt_integer, which
now contains integer code moved from here.
* src/lisp.h (GMP_NUMB_BITS): Define if gmp.h doesn’t.
Diffstat (limited to 'src')
| -rw-r--r-- | src/alloc.c | 73 | ||||
| -rw-r--r-- | src/data.c | 109 | ||||
| -rw-r--r-- | src/emacs.c | 34 | ||||
| -rw-r--r-- | src/floatfns.c | 24 | ||||
| -rw-r--r-- | src/lisp.h | 11 |
5 files changed, 167 insertions, 84 deletions
diff --git a/src/alloc.c b/src/alloc.c index ddc0696ba91..24a24aab96b 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -3746,33 +3746,33 @@ make_bignum_str (const char *num, int base) | |||
| 3746 | Lisp_Object | 3746 | Lisp_Object |
| 3747 | make_number (mpz_t value) | 3747 | make_number (mpz_t value) |
| 3748 | { | 3748 | { |
| 3749 | if (mpz_fits_slong_p (value)) | 3749 | size_t bits = mpz_sizeinbase (value, 2); |
| 3750 | { | 3750 | |
| 3751 | long l = mpz_get_si (value); | 3751 | if (bits <= FIXNUM_BITS) |
| 3752 | if (!FIXNUM_OVERFLOW_P (l)) | ||
| 3753 | return make_fixnum (l); | ||
| 3754 | } | ||
| 3755 | else if (LONG_WIDTH < FIXNUM_BITS) | ||
| 3756 | { | 3752 | { |
| 3757 | size_t bits = mpz_sizeinbase (value, 2); | 3753 | EMACS_INT v = 0; |
| 3754 | int i = 0, shift = 0; | ||
| 3758 | 3755 | ||
| 3759 | if (bits <= FIXNUM_BITS) | 3756 | do |
| 3760 | { | 3757 | { |
| 3761 | EMACS_INT v = 0; | 3758 | EMACS_INT limb = mpz_getlimbn (value, i++); |
| 3762 | int i = 0; | 3759 | v += limb << shift; |
| 3763 | for (int shift = 0; shift < bits; shift += mp_bits_per_limb) | 3760 | shift += GMP_NUMB_BITS; |
| 3764 | { | 3761 | } |
| 3765 | EMACS_INT limb = mpz_getlimbn (value, i++); | 3762 | while (shift < bits); |
| 3766 | v += limb << shift; | ||
| 3767 | } | ||
| 3768 | if (mpz_sgn (value) < 0) | ||
| 3769 | v = -v; | ||
| 3770 | 3763 | ||
| 3771 | if (!FIXNUM_OVERFLOW_P (v)) | 3764 | if (mpz_sgn (value) < 0) |
| 3772 | return make_fixnum (v); | 3765 | v = -v; |
| 3773 | } | 3766 | |
| 3767 | if (!FIXNUM_OVERFLOW_P (v)) | ||
| 3768 | return make_fixnum (v); | ||
| 3774 | } | 3769 | } |
| 3775 | 3770 | ||
| 3771 | /* The documentation says integer-width should be nonnegative, so | ||
| 3772 | a single comparison suffices even though 'bits' is unsigned. */ | ||
| 3773 | if (integer_width < bits) | ||
| 3774 | integer_overflow (); | ||
| 3775 | |||
| 3776 | struct Lisp_Bignum *b = ALLOCATE_PSEUDOVECTOR (struct Lisp_Bignum, value, | 3776 | struct Lisp_Bignum *b = ALLOCATE_PSEUDOVECTOR (struct Lisp_Bignum, value, |
| 3777 | PVEC_BIGNUM); | 3777 | PVEC_BIGNUM); |
| 3778 | /* We could mpz_init + mpz_swap here, to avoid a copy, but the | 3778 | /* We could mpz_init + mpz_swap here, to avoid a copy, but the |
| @@ -7200,6 +7200,26 @@ verify_alloca (void) | |||
| 7200 | 7200 | ||
| 7201 | #endif /* ENABLE_CHECKING && USE_STACK_LISP_OBJECTS */ | 7201 | #endif /* ENABLE_CHECKING && USE_STACK_LISP_OBJECTS */ |
| 7202 | 7202 | ||
| 7203 | /* Memory allocation for GMP. */ | ||
| 7204 | |||
| 7205 | void | ||
| 7206 | integer_overflow (void) | ||
| 7207 | { | ||
| 7208 | error ("Integer too large to be represented"); | ||
| 7209 | } | ||
| 7210 | |||
| 7211 | static void * | ||
| 7212 | xrealloc_for_gmp (void *ptr, size_t ignore, size_t size) | ||
| 7213 | { | ||
| 7214 | return xrealloc (ptr, size); | ||
| 7215 | } | ||
| 7216 | |||
| 7217 | static void | ||
| 7218 | xfree_for_gmp (void *ptr, size_t ignore) | ||
| 7219 | { | ||
| 7220 | xfree (ptr); | ||
| 7221 | } | ||
| 7222 | |||
| 7203 | /* Initialization. */ | 7223 | /* Initialization. */ |
| 7204 | 7224 | ||
| 7205 | void | 7225 | void |
| @@ -7233,6 +7253,10 @@ init_alloc_once (void) | |||
| 7233 | void | 7253 | void |
| 7234 | init_alloc (void) | 7254 | init_alloc (void) |
| 7235 | { | 7255 | { |
| 7256 | eassert (mp_bits_per_limb == GMP_NUMB_BITS); | ||
| 7257 | integer_width = 1 << 16; | ||
| 7258 | mp_set_memory_functions (xmalloc, xrealloc_for_gmp, xfree_for_gmp); | ||
| 7259 | |||
| 7236 | Vgc_elapsed = make_float (0.0); | 7260 | Vgc_elapsed = make_float (0.0); |
| 7237 | gcs_done = 0; | 7261 | gcs_done = 0; |
| 7238 | 7262 | ||
| @@ -7335,6 +7359,11 @@ The time is in seconds as a floating point value. */); | |||
| 7335 | DEFVAR_INT ("gcs-done", gcs_done, | 7359 | DEFVAR_INT ("gcs-done", gcs_done, |
| 7336 | doc: /* Accumulated number of garbage collections done. */); | 7360 | doc: /* Accumulated number of garbage collections done. */); |
| 7337 | 7361 | ||
| 7362 | DEFVAR_INT ("integer-width", integer_width, | ||
| 7363 | doc: /* Maximum number of bits in bignums. | ||
| 7364 | Integers outside the fixnum range are limited to absolute values less | ||
| 7365 | than 2**N, where N is this variable's value. N should be nonnegative. */); | ||
| 7366 | |||
| 7338 | defsubr (&Scons); | 7367 | defsubr (&Scons); |
| 7339 | defsubr (&Slist); | 7368 | defsubr (&Slist); |
| 7340 | defsubr (&Svector); | 7369 | defsubr (&Svector); |
diff --git a/src/data.c b/src/data.c index 8a6975da3ab..4c6d33f2940 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -2384,6 +2384,80 @@ bool-vector. IDX starts at 0. */) | |||
| 2384 | return newelt; | 2384 | return newelt; |
| 2385 | } | 2385 | } |
| 2386 | 2386 | ||
| 2387 | /* GMP tests for this value and aborts (!) if it is exceeded. | ||
| 2388 | This is as of GMP 6.1.2 (2016); perhaps future versions will differ. */ | ||
| 2389 | enum { GMP_NLIMBS_MAX = min (INT_MAX, ULONG_MAX / GMP_NUMB_BITS) }; | ||
| 2390 | |||
| 2391 | /* An upper bound on limb counts, needed to prevent libgmp and/or | ||
| 2392 | Emacs from aborting or otherwise misbehaving. This bound applies | ||
| 2393 | to estimates of mpz_t sizes before the mpz_t objects are created, | ||
| 2394 | as opposed to integer-width which operates on mpz_t values after | ||
| 2395 | creation and before conversion to Lisp bignums. */ | ||
| 2396 | enum | ||
| 2397 | { | ||
| 2398 | NLIMBS_LIMIT = min (min (/* libgmp needs to store limb counts. */ | ||
| 2399 | GMP_NLIMBS_MAX, | ||
| 2400 | |||
| 2401 | /* Size calculations need to work. */ | ||
| 2402 | min (PTRDIFF_MAX, SIZE_MAX) / sizeof (mp_limb_t)), | ||
| 2403 | |||
| 2404 | /* Emacs puts bit counts into fixnums. */ | ||
| 2405 | MOST_POSITIVE_FIXNUM / GMP_NUMB_BITS) | ||
| 2406 | }; | ||
| 2407 | |||
| 2408 | /* Like mpz_size, but tell the compiler the result is a nonnegative int. */ | ||
| 2409 | |||
| 2410 | static int | ||
| 2411 | emacs_mpz_size (mpz_t const op) | ||
| 2412 | { | ||
| 2413 | mp_size_t size = mpz_size (op); | ||
| 2414 | eassume (0 <= size && size <= INT_MAX); | ||
| 2415 | return size; | ||
| 2416 | } | ||
| 2417 | |||
| 2418 | /* Wrappers to work around GMP limitations. As of GMP 6.1.2 (2016), | ||
| 2419 | the library code aborts when a number is too large. These wrappers | ||
| 2420 | avoid the problem for functions that can return numbers much larger | ||
| 2421 | than their arguments. For slowly-growing numbers, the integer | ||
| 2422 | width check in make_number should suffice. */ | ||
| 2423 | |||
| 2424 | static void | ||
| 2425 | emacs_mpz_mul (mpz_t rop, mpz_t const op1, mpz_t const op2) | ||
| 2426 | { | ||
| 2427 | if (NLIMBS_LIMIT - emacs_mpz_size (op1) < emacs_mpz_size (op2)) | ||
| 2428 | integer_overflow (); | ||
| 2429 | mpz_mul (rop, op1, op2); | ||
| 2430 | } | ||
| 2431 | |||
| 2432 | static void | ||
| 2433 | emacs_mpz_mul_2exp (mpz_t rop, mpz_t const op1, mp_bitcnt_t op2) | ||
| 2434 | { | ||
| 2435 | /* Fudge factor derived from GMP 6.1.2, to avoid an abort in | ||
| 2436 | mpz_mul_2exp (look for the '+ 1' in its source code). */ | ||
| 2437 | enum { mul_2exp_extra_limbs = 1 }; | ||
| 2438 | enum { lim = min (NLIMBS_LIMIT, GMP_NLIMBS_MAX - mul_2exp_extra_limbs) }; | ||
| 2439 | |||
| 2440 | mp_bitcnt_t op2limbs = op2 / GMP_NUMB_BITS; | ||
| 2441 | if (lim - emacs_mpz_size (op1) < op2limbs) | ||
| 2442 | integer_overflow (); | ||
| 2443 | mpz_mul_2exp (rop, op1, op2); | ||
| 2444 | } | ||
| 2445 | |||
| 2446 | static void | ||
| 2447 | emacs_mpz_pow_ui (mpz_t rop, mpz_t const base, unsigned long exp) | ||
| 2448 | { | ||
| 2449 | /* This fudge factor is derived from GMP 6.1.2, to avoid an abort in | ||
| 2450 | mpz_n_pow_ui (look for the '5' in its source code). */ | ||
| 2451 | enum { pow_ui_extra_limbs = 5 }; | ||
| 2452 | enum { lim = min (NLIMBS_LIMIT, GMP_NLIMBS_MAX - pow_ui_extra_limbs) }; | ||
| 2453 | |||
| 2454 | int nbase = emacs_mpz_size (base), n; | ||
| 2455 | if (INT_MULTIPLY_WRAPV (nbase, exp, &n) || lim < n) | ||
| 2456 | integer_overflow (); | ||
| 2457 | mpz_pow_ui (rop, base, exp); | ||
| 2458 | } | ||
| 2459 | |||
| 2460 | |||
| 2387 | /* Arithmetic functions */ | 2461 | /* Arithmetic functions */ |
| 2388 | 2462 | ||
| 2389 | Lisp_Object | 2463 | Lisp_Object |
| @@ -2872,13 +2946,13 @@ arith_driver (enum arithop code, ptrdiff_t nargs, Lisp_Object *args) | |||
| 2872 | break; | 2946 | break; |
| 2873 | case Amult: | 2947 | case Amult: |
| 2874 | if (BIGNUMP (val)) | 2948 | if (BIGNUMP (val)) |
| 2875 | mpz_mul (accum, accum, XBIGNUM (val)->value); | 2949 | emacs_mpz_mul (accum, accum, XBIGNUM (val)->value); |
| 2876 | else if (! FIXNUMS_FIT_IN_LONG) | 2950 | else if (! FIXNUMS_FIT_IN_LONG) |
| 2877 | { | 2951 | { |
| 2878 | mpz_t tem; | 2952 | mpz_t tem; |
| 2879 | mpz_init (tem); | 2953 | mpz_init (tem); |
| 2880 | mpz_set_intmax (tem, XFIXNUM (val)); | 2954 | mpz_set_intmax (tem, XFIXNUM (val)); |
| 2881 | mpz_mul (accum, accum, tem); | 2955 | emacs_mpz_mul (accum, accum, tem); |
| 2882 | mpz_clear (tem); | 2956 | mpz_clear (tem); |
| 2883 | } | 2957 | } |
| 2884 | else | 2958 | else |
| @@ -3293,7 +3367,7 @@ In this case, the sign bit is duplicated. */) | |||
| 3293 | mpz_t result; | 3367 | mpz_t result; |
| 3294 | mpz_init (result); | 3368 | mpz_init (result); |
| 3295 | if (XFIXNUM (count) > 0) | 3369 | if (XFIXNUM (count) > 0) |
| 3296 | mpz_mul_2exp (result, XBIGNUM (value)->value, XFIXNUM (count)); | 3370 | emacs_mpz_mul_2exp (result, XBIGNUM (value)->value, XFIXNUM (count)); |
| 3297 | else | 3371 | else |
| 3298 | mpz_fdiv_q_2exp (result, XBIGNUM (value)->value, - XFIXNUM (count)); | 3372 | mpz_fdiv_q_2exp (result, XBIGNUM (value)->value, - XFIXNUM (count)); |
| 3299 | val = make_number (result); | 3373 | val = make_number (result); |
| @@ -3319,7 +3393,7 @@ In this case, the sign bit is duplicated. */) | |||
| 3319 | mpz_set_intmax (result, XFIXNUM (value)); | 3393 | mpz_set_intmax (result, XFIXNUM (value)); |
| 3320 | 3394 | ||
| 3321 | if (XFIXNUM (count) >= 0) | 3395 | if (XFIXNUM (count) >= 0) |
| 3322 | mpz_mul_2exp (result, result, XFIXNUM (count)); | 3396 | emacs_mpz_mul_2exp (result, result, XFIXNUM (count)); |
| 3323 | else | 3397 | else |
| 3324 | mpz_fdiv_q_2exp (result, result, - XFIXNUM (count)); | 3398 | mpz_fdiv_q_2exp (result, result, - XFIXNUM (count)); |
| 3325 | 3399 | ||
| @@ -3330,6 +3404,33 @@ In this case, the sign bit is duplicated. */) | |||
| 3330 | return val; | 3404 | return val; |
| 3331 | } | 3405 | } |
| 3332 | 3406 | ||
| 3407 | /* Return X ** Y as an integer. X and Y must be integers, and Y must | ||
| 3408 | be nonnegative. */ | ||
| 3409 | |||
| 3410 | Lisp_Object | ||
| 3411 | expt_integer (Lisp_Object x, Lisp_Object y) | ||
| 3412 | { | ||
| 3413 | unsigned long exp; | ||
| 3414 | if (TYPE_RANGED_FIXNUMP (unsigned long, y)) | ||
| 3415 | exp = XFIXNUM (y); | ||
| 3416 | else if (MOST_POSITIVE_FIXNUM < ULONG_MAX && BIGNUMP (y) | ||
| 3417 | && mpz_fits_ulong_p (XBIGNUM (y)->value)) | ||
| 3418 | exp = mpz_get_ui (XBIGNUM (y)->value); | ||
| 3419 | else | ||
| 3420 | integer_overflow (); | ||
| 3421 | |||
| 3422 | mpz_t val; | ||
| 3423 | mpz_init (val); | ||
| 3424 | emacs_mpz_pow_ui (val, | ||
| 3425 | (FIXNUMP (x) | ||
| 3426 | ? (mpz_set_intmax (val, XFIXNUM (x)), val) | ||
| 3427 | : XBIGNUM (x)->value), | ||
| 3428 | exp); | ||
| 3429 | Lisp_Object res = make_number (val); | ||
| 3430 | mpz_clear (val); | ||
| 3431 | return res; | ||
| 3432 | } | ||
| 3433 | |||
| 3333 | DEFUN ("1+", Fadd1, Sadd1, 1, 1, 0, | 3434 | DEFUN ("1+", Fadd1, Sadd1, 1, 1, 0, |
| 3334 | doc: /* Return NUMBER plus one. NUMBER may be a number or a marker. | 3435 | doc: /* Return NUMBER plus one. NUMBER may be a number or a marker. |
| 3335 | Markers are converted to integers. */) | 3436 | Markers are converted to integers. */) |
diff --git a/src/emacs.c b/src/emacs.c index 11ee0b81180..7d07ec85029 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -673,38 +673,6 @@ close_output_streams (void) | |||
| 673 | _exit (EXIT_FAILURE); | 673 | _exit (EXIT_FAILURE); |
| 674 | } | 674 | } |
| 675 | 675 | ||
| 676 | /* Memory allocation functions for GMP. */ | ||
| 677 | |||
| 678 | static void | ||
| 679 | check_bignum_size (size_t size) | ||
| 680 | { | ||
| 681 | /* Do not create a bignum whose log base 2 could exceed fixnum range. | ||
| 682 | This way, functions like mpz_popcount return values in fixnum range. | ||
| 683 | It may also help to avoid other problems with outlandish bignums. */ | ||
| 684 | if (MOST_POSITIVE_FIXNUM / CHAR_BIT < size) | ||
| 685 | error ("Integer too large to be represented"); | ||
| 686 | } | ||
| 687 | |||
| 688 | static void * ATTRIBUTE_MALLOC | ||
| 689 | xmalloc_for_gmp (size_t size) | ||
| 690 | { | ||
| 691 | check_bignum_size (size); | ||
| 692 | return xmalloc (size); | ||
| 693 | } | ||
| 694 | |||
| 695 | static void * | ||
| 696 | xrealloc_for_gmp (void *ptr, size_t ignore, size_t size) | ||
| 697 | { | ||
| 698 | check_bignum_size (size); | ||
| 699 | return xrealloc (ptr, size); | ||
| 700 | } | ||
| 701 | |||
| 702 | static void | ||
| 703 | xfree_for_gmp (void *ptr, size_t ignore) | ||
| 704 | { | ||
| 705 | xfree (ptr); | ||
| 706 | } | ||
| 707 | |||
| 708 | /* ARGSUSED */ | 676 | /* ARGSUSED */ |
| 709 | int | 677 | int |
| 710 | main (int argc, char **argv) | 678 | main (int argc, char **argv) |
| @@ -803,8 +771,6 @@ main (int argc, char **argv) | |||
| 803 | init_standard_fds (); | 771 | init_standard_fds (); |
| 804 | atexit (close_output_streams); | 772 | atexit (close_output_streams); |
| 805 | 773 | ||
| 806 | mp_set_memory_functions (xmalloc_for_gmp, xrealloc_for_gmp, xfree_for_gmp); | ||
| 807 | |||
| 808 | sort_args (argc, argv); | 774 | sort_args (argc, argv); |
| 809 | argc = 0; | 775 | argc = 0; |
| 810 | while (argv[argc]) argc++; | 776 | while (argv[argc]) argc++; |
diff --git a/src/floatfns.c b/src/floatfns.c index 7c52a0a9a20..ea9000b90a0 100644 --- a/src/floatfns.c +++ b/src/floatfns.c | |||
| @@ -210,29 +210,7 @@ DEFUN ("expt", Fexpt, Sexpt, 2, 2, 0, | |||
| 210 | /* Common Lisp spec: don't promote if both are integers, and if the | 210 | /* Common Lisp spec: don't promote if both are integers, and if the |
| 211 | result is not fractional. */ | 211 | result is not fractional. */ |
| 212 | if (INTEGERP (arg1) && NATNUMP (arg2)) | 212 | if (INTEGERP (arg1) && NATNUMP (arg2)) |
| 213 | { | 213 | return expt_integer (arg1, arg2); |
| 214 | unsigned long exp; | ||
| 215 | if (TYPE_RANGED_FIXNUMP (unsigned long, arg2)) | ||
| 216 | exp = XFIXNUM (arg2); | ||
| 217 | else if (MOST_POSITIVE_FIXNUM < ULONG_MAX && BIGNUMP (arg2) | ||
| 218 | && mpz_fits_ulong_p (XBIGNUM (arg2)->value)) | ||
| 219 | exp = mpz_get_ui (XBIGNUM (arg2)->value); | ||
| 220 | else | ||
| 221 | xsignal3 (Qrange_error, build_string ("expt"), arg1, arg2); | ||
| 222 | |||
| 223 | mpz_t val; | ||
| 224 | mpz_init (val); | ||
| 225 | if (FIXNUMP (arg1)) | ||
| 226 | { | ||
| 227 | mpz_set_intmax (val, XFIXNUM (arg1)); | ||
| 228 | mpz_pow_ui (val, val, exp); | ||
| 229 | } | ||
| 230 | else | ||
| 231 | mpz_pow_ui (val, XBIGNUM (arg1)->value, exp); | ||
| 232 | Lisp_Object res = make_number (val); | ||
| 233 | mpz_clear (val); | ||
| 234 | return res; | ||
| 235 | } | ||
| 236 | 214 | ||
| 237 | return make_float (pow (XFLOATINT (arg1), XFLOATINT (arg2))); | 215 | return make_float (pow (XFLOATINT (arg1), XFLOATINT (arg2))); |
| 238 | } | 216 | } |
diff --git a/src/lisp.h b/src/lisp.h index fe384d1844b..8f48a334844 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -996,6 +996,14 @@ enum More_Lisp_Bits | |||
| 996 | #define MOST_POSITIVE_FIXNUM (EMACS_INT_MAX >> INTTYPEBITS) | 996 | #define MOST_POSITIVE_FIXNUM (EMACS_INT_MAX >> INTTYPEBITS) |
| 997 | #define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM) | 997 | #define MOST_NEGATIVE_FIXNUM (-1 - MOST_POSITIVE_FIXNUM) |
| 998 | 998 | ||
| 999 | |||
| 1000 | /* GMP-related limits. */ | ||
| 1001 | |||
| 1002 | /* Number of data bits in a limb. */ | ||
| 1003 | #ifndef GMP_NUMB_BITS | ||
| 1004 | enum { GMP_NUMB_BITS = TYPE_WIDTH (mp_limb_t) }; | ||
| 1005 | #endif | ||
| 1006 | |||
| 999 | #if USE_LSB_TAG | 1007 | #if USE_LSB_TAG |
| 1000 | 1008 | ||
| 1001 | INLINE Lisp_Object | 1009 | INLINE Lisp_Object |
| @@ -3338,7 +3346,7 @@ extern void set_internal (Lisp_Object, Lisp_Object, Lisp_Object, | |||
| 3338 | enum Set_Internal_Bind); | 3346 | enum Set_Internal_Bind); |
| 3339 | extern void set_default_internal (Lisp_Object, Lisp_Object, | 3347 | extern void set_default_internal (Lisp_Object, Lisp_Object, |
| 3340 | enum Set_Internal_Bind bindflag); | 3348 | enum Set_Internal_Bind bindflag); |
| 3341 | 3349 | extern Lisp_Object expt_integer (Lisp_Object, Lisp_Object); | |
| 3342 | extern void syms_of_data (void); | 3350 | extern void syms_of_data (void); |
| 3343 | extern void swap_in_global_binding (struct Lisp_Symbol *); | 3351 | extern void swap_in_global_binding (struct Lisp_Symbol *); |
| 3344 | 3352 | ||
| @@ -3700,6 +3708,7 @@ extern void display_malloc_warning (void); | |||
| 3700 | extern ptrdiff_t inhibit_garbage_collection (void); | 3708 | extern ptrdiff_t inhibit_garbage_collection (void); |
| 3701 | extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object); | 3709 | extern Lisp_Object build_overlay (Lisp_Object, Lisp_Object, Lisp_Object); |
| 3702 | extern void free_cons (struct Lisp_Cons *); | 3710 | extern void free_cons (struct Lisp_Cons *); |
| 3711 | extern _Noreturn void integer_overflow (void); | ||
| 3703 | extern void init_alloc_once (void); | 3712 | extern void init_alloc_once (void); |
| 3704 | extern void init_alloc (void); | 3713 | extern void init_alloc (void); |
| 3705 | extern void syms_of_alloc (void); | 3714 | extern void syms_of_alloc (void); |