[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#22406: Cannot compile for Windows x64 due to LLP64 model
From: 
Mark H Weaver 
Subject: 
bug#22406: Cannot compile for Windows x64 due to LLP64 model 
Date: 
Tue, 26 Jan 2016 11:02:17 0500 
Useragent: 
Gnus/5.13 (Gnus v5.13) Emacs/24.5 (gnu/linux) 
Hi Peter,
Peter TB Brett <address@hidden> writes:
> It is not currently possible to compile Guile 2.0.11 for Windows x64
> (in particular 64bit Windows running on the x8664 arch).
>
> Most operating systems' C libraries for x8664 use an "LP64" model,
> where sizeof(long int) == sizeof(void *) == 8.
>
> However, for backwardscompatibility reasons, Windows uses an "LLP64"
> model, where sizeof(long long int) == sizeof(void *) == 8 and
> sizeof(long int) == 4.
>
> Guile 2.0.11 can't cope with this; the libguile build fails due to
> this code:
I've attached a patch that attempts to address this issue by using
'long' as the scm_t_inum type. So, fixnums will be limited to 30 bits
on LLP64 systems. We can't easily avoid this while using GMP's mpz API,
since the mpz_*_si functions except longs and there are no analogous
functions that accept larger C integer types.
Can you test this patch and report back?
Thanks,
Mark
>From 4a923816c9814b07556fdcc53b74b3e1ca2a0f41 Mon Sep 17 00:00:00 2001
From: Mark H Weaver <address@hidden>
Date: Tue, 26 Jan 2016 03:42:18 0500
Subject: [PATCH] PRELIMINARY fixes for LLP64.

libguile/numbers.c  19 ++++++++++
libguile/numbers.h  29 ++++++++++++++
libguile/vmischeme.c  2 +
3 files changed, 25 insertions(+), 25 deletions()
diff git a/libguile/numbers.c b/libguile/numbers.c
index 1e3fc30..7d32c20 100644
 a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ 1,4 +1,4 @@
/* Copyright (C) 19952015 Free Software Foundation, Inc.
+/* Copyright (C) 19952016 Free Software Foundation, Inc.
*
* Portions Copyright 1990, 1991, 1992, 1993 by AT&T Bell Laboratories
* and Bellcore. See scm_divide.
@@ 87,7 +87,14 @@
/* FIXME: We assume that FLT_RADIX is 2 */
verify (FLT_RADIX == 2);
typedef scm_t_signed_bits scm_t_inum;
+/* We assume that a long fits within a SCM value. */
+verify (SCM_SIZEOF_LONG <= SIZEOF_SCM_T_BITS);
+
+/* We use 'long' as the type for Inums, because that's the type accepted
+ by GMP's mpz_*_si functions. Above, we checked that a long fits
+ within an SCM. */
+typedef long scm_t_inum;
+
#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
@@ 272,13 +279,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;
}
@@ 4966,7 +4967,7 @@ left_shift_exact_integer (SCM n, long count)
if (nn == 0)
return n;
else if (count < SCM_I_FIXNUM_BIT1 &&
 ((scm_t_bits) (SCM_SRS (nn, (SCM_I_FIXNUM_BIT1  count)) + 1)
+ ((unsigned long) (SCM_SRS (nn, (SCM_I_FIXNUM_BIT1  count)) +
1)
<= 1))
return SCM_I_MAKINUM (nn < 0 ? (nn << count) : (nn << count));
else
diff git a/libguile/numbers.h b/libguile/numbers.h
index b929b7a..d5e4f2b 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, 20002006, 20082011, 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. We assume that
+ * a long fits in a SCM value (this is checked in numbers.c). */
#define SCM_I_FIXNUM_BIT (SCM_LONG_BIT  2)
#define SCM_MOST_POSITIVE_FIXNUM ((SCM_T_SIGNED_BITS_MAX3)/4)
#define SCM_MOST_NEGATIVE_FIXNUM (SCM_MOST_POSITIVE_FIXNUM1)
+#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 nonnegative and less than the width in bits of X.
@@ 60,7 +59,7 @@ typedef scm_t_int32 scm_t_wchar;
#else
# define SCM_SRS(x, y) \
((x) < 0 \
 ? 1  (scm_t_signed_bits) (~(scm_t_bits)(x) >> (y)) \
+ ? 1  (long) (~(unsigned long)(x) >> (y)) \
: ((x) >> (y)))
#endif
@@ 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 ((long) 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))
+ ? 1  (long) (~SCM_UNPACK (x) >> 2) \
+ : (long) (SCM_UNPACK (x) >> 2))
#endif
#define SCM_I_INUMP(x) (2 & SCM_UNPACK (x))
diff git a/libguile/vmischeme.c b/libguile/vmischeme.c
index 162efab..249b835 100644
 a/libguile/vmischeme.c
+++ b/libguile/vmischeme.c
@@ 360,7 +360,7 @@ VM_DEFINE_FUNCTION (149, ge, "ge?", 2)
# define ASM_MUL(x, y)
\
if (SCM_LIKELY (SCM_I_INUMP (x) && SCM_I_INUMP (y))) \
{
\
 scm_t_signed_bits rlo, rhi; \
+ long rlo, rhi; \
asm ("smull %0, %1, %2, %3\n" \
: "=&r" (rlo), "=&r" (rhi) \
: "r" (SCM_UNPACK (x)  scm_tc2_int), \

2.6.3