1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 03:30:27 +02:00

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 *).
This commit is contained in:
Mark H Weaver 2016-04-06 17:36:57 -04:00 committed by Andy Wingo
parent a8d1c7d610
commit 1d257c27f0
2 changed files with 18 additions and 23 deletions

View file

@ -86,7 +86,9 @@
/* FIXME: We assume that FLT_RADIX is 2 */ /* FIXME: We assume that FLT_RADIX is 2 */
verify (FLT_RADIX == 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)) #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 /* 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. */ /* Return a newly created bignum initialized to X. */
SCM z = make_bignum (); SCM z = make_bignum ();
#if SIZEOF_VOID_P == SIZEOF_LONG
mpz_init_set_si (SCM_I_BIG_MPZ (z), x); 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; return z;
} }

View file

@ -3,8 +3,8 @@
#ifndef SCM_NUMBERS_H #ifndef SCM_NUMBERS_H
#define SCM_NUMBERS_H #define SCM_NUMBERS_H
/* Copyright (C) 1995,1996,1998,2000,2001,2002,2003,2004,2005, 2006, /* Copyright (C) 1995, 1996, 1998, 2000-2006, 2008-2011, 2013, 2014,
* 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. * 2016 Free Software Foundation, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * 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 /* Immediate Numbers, also known as fixnums
* *
* Inums are exact integer data that fits within an SCM word. */ * Inums are exact integers that fit within an SCM word
* (along with two tagging bits).
/* SCM_T_SIGNED_MAX is (- (expt 2 n) 1), *
* SCM_MOST_POSITIVE_FIXNUM should be (- (expt 2 (- n 2)) 1) * In the current implementation, Inums must also fit within a long
* which is the same as (/ (- (expt 2 n) 4) 4) * 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_I_FIXNUM_BIT (SCM_LONG_BIT - 2)
#define SCM_MOST_POSITIVE_FIXNUM ((SCM_T_SIGNED_BITS_MAX-3)/4) #define SCM_MOST_NEGATIVE_FIXNUM (-1L << (SCM_I_FIXNUM_BIT - 1))
#define SCM_MOST_NEGATIVE_FIXNUM (-SCM_MOST_POSITIVE_FIXNUM-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), /* 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. 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. */ NOTE: X must not perform side effects. */
#ifdef __GNUC__ #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 #else
# define SCM_I_INUM(x) \ # define SCM_I_INUM(x) \
(SCM_UNPACK (x) > LONG_MAX \ (SCM_UNPACK (x) > SCM_T_SIGNED_BITS_MAX \
? -1 - (scm_t_signed_bits) (~SCM_UNPACK (x) >> 2) \ ? -1 - (scm_t_inum) (~SCM_UNPACK (x) >> 2) \
: (scm_t_signed_bits) (SCM_UNPACK (x) >> 2)) : (scm_t_inum) (SCM_UNPACK (x) >> 2))
#endif #endif
#define SCM_I_INUMP(x) (2 & SCM_UNPACK (x)) #define SCM_I_INUMP(x) (2 & SCM_UNPACK (x))