From 04204c2fbf4cb7db7e6b1ce8691ef99f7610f0ee Mon Sep 17 00:00:00 2001
From: Richard Henderson <rth@redhat.com>
Date: Sun, 29 Aug 2004 21:47:49 -0700
Subject: [PATCH] trans-const.c (gfc_conv_mpz_to_tree): Use mpz_export.

        * trans-const.c (gfc_conv_mpz_to_tree): Use mpz_export.
        * trans-types.c (gfc_init_kinds): Reject integer kinds larger
        than two HOST_WIDE_INT.

From-SVN: r86749
---
 gcc/fortran/ChangeLog     |  6 +++++
 gcc/fortran/trans-const.c | 50 +++++++++++++++------------------------
 gcc/fortran/trans-types.c |  8 ++++++-
 3 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index d1f3edb2b8f4..d7a4cebc75b7 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,9 @@
+2004-08-29  Richard Henderson  <rth@redhat.com>
+
+	* trans-const.c (gfc_conv_mpz_to_tree): Use mpz_export.
+	* trans-types.c (gfc_init_kinds): Reject integer kinds larger
+	than two HOST_WIDE_INT.
+
 2004-08-29  Tobias Schlueter  <tobias.schlueter@physik.uni-muenchen.de>
 
 	PR fortran/13910
diff --git a/gcc/fortran/trans-const.c b/gcc/fortran/trans-const.c
index 56687273e175..10f701aeb6fa 100644
--- a/gcc/fortran/trans-const.c
+++ b/gcc/fortran/trans-const.c
@@ -176,39 +176,27 @@ gfc_conv_mpz_to_tree (mpz_t i, int kind)
     }
   else
     {
-      /* Note that mp_limb_t can be anywhere from short to long long,
-	 which gives us a nice variety of cases to choose from.  */
+      unsigned HOST_WIDE_INT words[2];
+      size_t count;
 
-      if (sizeof (mp_limb_t) == sizeof (HOST_WIDE_INT))
-	{
-	  low = mpz_getlimbn (i, 0);
-	  high = mpz_getlimbn (i, 1);
-	}
-      else if (sizeof (mp_limb_t) == 2 * sizeof (HOST_WIDE_INT))
-	{
-	  mp_limb_t limb0 = mpz_getlimbn (i, 0);
-	  int shift = (sizeof (mp_limb_t) - sizeof (HOST_WIDE_INT)) * CHAR_BIT;
-	  low = limb0;
-	  high = limb0 >> shift;
-	}
-      else if (sizeof (mp_limb_t) < sizeof (HOST_WIDE_INT))
-	{
-	  int shift = sizeof (mp_limb_t) * CHAR_BIT;
-	  int n, count = sizeof (HOST_WIDE_INT) / sizeof (mp_limb_t);
-	  for (low = n = 0; n < count; ++n)
-	    {
-	      low <<= shift;
-	      low |= mpz_getlimbn (i, n);
-	    }
-	  for (high = 0, n = count; n < 2*count; ++n)
-	    {
-	      high <<= shift;
-	      high |= mpz_getlimbn (i, n);
-	    }
-	}
+      /* Since we know that the value is not zero (mpz_fits_slong_p),
+	 we know that at one word will be written, but we don't know
+	 about the second.  It's quicker to zero the second word before
+	 that conditionally clear it later.  */
+      words[1] = 0;
 
-      /* By extracting limbs we constructed the absolute value of the
-	 desired number.  Negate if necessary.  */
+      /* Extract the absolute value into words.  */
+      mpz_export (words, &count, -1, sizeof (HOST_WIDE_INT), 0, 0, i);
+
+      /* We assume that all numbers are in range for its type, and that
+	 we never create a type larger than 2*HWI, which is the largest
+	 that the middle-end can handle.  */
+      assert (count == 1 || count == 2);
+
+      low = words[0];
+      high = words[1];
+
+      /* Negate if necessary.  */
       if (mpz_sgn (i) < 0)
 	{
 	  if (low == 0)
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index d1ace6dac50e..def726200be9 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -104,12 +104,18 @@ gfc_init_kinds (void)
       if (!targetm.scalar_mode_supported_p (mode))
 	continue;
 
+      /* The middle end doesn't support constants larger than 2*HWI.
+	 Perhaps the target hook shouldn't have accepted these either,
+	 but just to be safe...  */
+      bitsize = GET_MODE_BITSIZE (mode);
+      if (bitsize > 2*HOST_BITS_PER_WIDE_INT)
+	continue;
+
       if (i_index == MAX_INT_KINDS)
 	abort ();
 
       /* Let the kind equal the bit size divided by 8.  This insulates the
 	 programmer from the underlying byte size.  */
-      bitsize = GET_MODE_BITSIZE (mode);
       kind = bitsize / 8;
 
       if (kind == 4)