diff options
author | Mark H Weaver <mhw@netris.org> | 2016-04-06 17:36:57 -0400 |
---|---|---|
committer | Andy Wingo <wingo@pobox.com> | 2017-03-01 19:08:42 +0100 |
commit | 1d257c27f004fe4db81d62033b5cf2d8fafcd68f (patch) | |
tree | b411ac6606fa9f64e502d51e59e9a6b042a7f785 /libguile | |
parent | a8d1c7d61018bb2c77c6ffd57f3c1672361ce1e9 (diff) |
Do not assume that sizeof (long) == sizeof (void *) == sizeof (SCM).
This assumption does not hold on systems that use the LLP64 data model.
Partially fixes <https://debbugs.gnu.org/22406>.
Reported by Peter TB Brett <peter@peter-b.co.uk>.
* libguile/numbers.h (scm_t_inum): Move here from numbers.c, and change
to be equivalent to 'long' (formerly 'scm_t_signed_bits').
(SCM_MOST_POSITIVE_FIXNUM, SCM_MOST_NEGATIVE_FIXNUM): Define based on
SCM_I_FIXNUM_BIT instead of SCM_T_SIGNED_BITS_MAX.
(SCM_I_INUM): Adjust definitions to return a 'scm_t_inum', and avoiding
the assumption that SCM_UNPACK returns a 'long'.
* libguile/numbers.c (scm_t_inum): Move definition to numbers.h.
Verify that 'scm_t_inum' fits within a SCM value.
(scm_i_inum2big): Remove preprocessor code that forced a compile error
unless sizeof (long) == sizeof (void *).
Diffstat (limited to 'libguile')
-rw-r--r-- | libguile/numbers.c | 10 | ||||
-rw-r--r-- | libguile/numbers.h | 31 |
2 files changed, 18 insertions, 23 deletions
diff --git a/libguile/numbers.c b/libguile/numbers.c index 34980c6a9..3e0efc8bb 100644 --- a/libguile/numbers.c +++ b/libguile/numbers.c @@ -86,7 +86,9 @@ /* FIXME: We assume that FLT_RADIX is 2 */ verify (FLT_RADIX == 2); -typedef scm_t_signed_bits scm_t_inum; +/* Make sure that scm_t_inum fits within a SCM value. */ +verify (sizeof (scm_t_inum) <= sizeof (scm_t_bits)); + #define scm_from_inum(x) (scm_from_signed_integer (x)) /* Test an inum to see if it can be converted to a double without loss @@ -271,13 +273,7 @@ scm_i_inum2big (scm_t_inum x) { /* Return a newly created bignum initialized to X. */ SCM z = make_bignum (); -#if SIZEOF_VOID_P == SIZEOF_LONG mpz_init_set_si (SCM_I_BIG_MPZ (z), x); -#else - /* Note that in this case, you'll also have to check all mpz_*_ui and - mpz_*_si invocations in Guile. */ -#error creation of mpz not implemented for this inum size -#endif return z; } diff --git a/libguile/numbers.h b/libguile/numbers.h index bba336bd4..d2799b1c6 100644 --- a/libguile/numbers.h +++ b/libguile/numbers.h @@ -3,8 +3,8 @@ #ifndef SCM_NUMBERS_H #define SCM_NUMBERS_H -/* Copyright (C) 1995,1996,1998,2000,2001,2002,2003,2004,2005, 2006, - * 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996, 1998, 2000-2006, 2008-2011, 2013, 2014, + * 2016 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -38,16 +38,15 @@ typedef scm_t_int32 scm_t_wchar; /* Immediate Numbers, also known as fixnums * - * Inums are exact integer data that fits within an SCM word. */ - -/* SCM_T_SIGNED_MAX is (- (expt 2 n) 1), - * SCM_MOST_POSITIVE_FIXNUM should be (- (expt 2 (- n 2)) 1) - * which is the same as (/ (- (expt 2 n) 4) 4) - */ - + * Inums are exact integers that fit within an SCM word + * (along with two tagging bits). + * + * In the current implementation, Inums must also fit within a long + * because that's what GMP's mpz_*_si functions accept. */ +typedef long scm_t_inum; #define SCM_I_FIXNUM_BIT (SCM_LONG_BIT - 2) -#define SCM_MOST_POSITIVE_FIXNUM ((SCM_T_SIGNED_BITS_MAX-3)/4) -#define SCM_MOST_NEGATIVE_FIXNUM (-SCM_MOST_POSITIVE_FIXNUM-1) +#define SCM_MOST_NEGATIVE_FIXNUM (-1L << (SCM_I_FIXNUM_BIT - 1)) +#define SCM_MOST_POSITIVE_FIXNUM (- (SCM_MOST_NEGATIVE_FIXNUM + 1)) /* SCM_SRS (X, Y) is signed right shift, defined as floor (X / 2^Y), where Y must be non-negative and less than the width in bits of X. @@ -74,12 +73,12 @@ typedef scm_t_int32 scm_t_wchar; NOTE: X must not perform side effects. */ #ifdef __GNUC__ -# define SCM_I_INUM(x) (SCM_SRS ((scm_t_signed_bits) SCM_UNPACK (x), 2)) +# define SCM_I_INUM(x) (SCM_SRS ((scm_t_inum) SCM_UNPACK (x), 2)) #else -# define SCM_I_INUM(x) \ - (SCM_UNPACK (x) > LONG_MAX \ - ? -1 - (scm_t_signed_bits) (~SCM_UNPACK (x) >> 2) \ - : (scm_t_signed_bits) (SCM_UNPACK (x) >> 2)) +# define SCM_I_INUM(x) \ + (SCM_UNPACK (x) > SCM_T_SIGNED_BITS_MAX \ + ? -1 - (scm_t_inum) (~SCM_UNPACK (x) >> 2) \ + : (scm_t_inum) (SCM_UNPACK (x) >> 2)) #endif #define SCM_I_INUMP(x) (2 & SCM_UNPACK (x)) |