This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: status of wide-int patch.


Kyrill Tkachov <kyrylo.tkachov@arm.com> writes:
> On 28/04/14 18:03, Kenneth Zadeck wrote:
>> At this point we have believe that we have addressed all of the concerns
>> that the community has made about the wide-int branch.   We have also
>> had each of the sections of the branch approved by the area maintainers.
>>
>> We are awaiting a clean build on the arm
>
> Unfortunately arm bootstrap fails a bit further down the line in stage2 while 
> building libstdc++-v3/src/c++98/ios.cc:
>
> xgcc: internal compiler error: Segmentation fault (program cc1plus)
> Please submit a full bug report,
> with preprocessed source if appropriate.
> See <http://gcc.gnu.org/bugs.html> for instructions.
>
> Running the cc1plus subcommand through gdb gives:
> Program received signal SIGSEGV, Segmentation fault.
> 0x005c32c8 in real_to_decimal_for_mode(char*, real_value const*, unsigned int, 
> unsigned int, int, machine_mode) ()
> (gdb) bt
> #0  0x005c32c8 in real_to_decimal_for_mode(char*, real_value const*, unsigned 
> int, unsigned int, int, machine_mode) ()
> #1  0x000033f6 in ?? ()
> Backtrace stopped: previous frame identical to this frame (corrupt stack?)
> (gdb)
>
> The debug info seems to be scarce here, any hints on where to look?

I saw the same thing on 32-bit s390-linux-gnu.  It was due to a bug
in the HOST_BITS_PER_WIDE_INT != HOST_BITS_PER_LONG part of real_to_integer,
which would read from before the sig[] buffer if the array size is odd.

The conversion to real_int also meant that we were passing the bit count
"w" to the "need_canon_p" parameter of from_array.  "w" looks bogus to me;
the integer that we're constructing in val[] has precision
"words * HOST_BITS_PER_WIDE_INT", with the top bit being the same
as the significand.  It seems simpler to do the operation on that
precision instead.  This also avoids the need for a fixed_wide_int,
since "words * HOST_BITS_PER_WIDE_INT" takes the same number of HWIs
as the final wide_int result.

This patch seems to fix the failure for me and means that the stage2
real.s produced on s390-linux-gnu is the same as that produced by
s390x-linux-gnu -m31.  I'll test on s390-linux-gnu overnight.

Thanks,
Richard


Index: gcc/real.c
===================================================================
--- gcc/real.c	(revision 209874)
+++ gcc/real.c	(working copy)
@@ -1377,13 +1377,10 @@
 wide_int
 real_to_integer (const REAL_VALUE_TYPE *r, bool *fail, int precision)
 {
-  typedef FIXED_WIDE_INT (WIDE_INT_MAX_PRECISION * 2) real_int;
-  HOST_WIDE_INT val[2 * MAX_BITSIZE_MODE_ANY_INT / HOST_BITS_PER_WIDE_INT];
+  HOST_WIDE_INT val[2 * WIDE_INT_MAX_ELTS];
   int exp;
-  int words;
+  int words, w;
   wide_int result;
-  real_int tmp;
-  int w;
 
   switch (r->cl)
     {
@@ -1415,11 +1412,13 @@
       if (exp > precision)
 	goto overflow;
 
+      /* Put the significand into a wide_int that has precision W, which
+	 is the smallest HWI-multiple that has at least PRECISION bits.
+	 This ensures that the top bit of the significand is in the
+	 top bit of the wide_int.  */
       words = (precision + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT;
+      w = words * HOST_BITS_PER_WIDE_INT;
 
-      for (unsigned int i = 0; i < ARRAY_SIZE (val); i++)
-	val[i] = 0;
-
 #if (HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG)
       for (int i = 0; i < words; i++)
 	{
@@ -1427,27 +1426,23 @@
 	  val[i] = (j < 0) ? 0 : r->sig[j];
 	}
 #else
-      gcc_assert (HOST_BITS_PER_WIDE_INT == 2*HOST_BITS_PER_LONG);
+      gcc_assert (HOST_BITS_PER_WIDE_INT == 2 * HOST_BITS_PER_LONG);
       for (int i = 0; i < words; i++)
 	{
-	  int j = SIGSZ - (words * 2) + (i + 2) + 1;
+	  int j = SIGSZ - (words * 2) + (i * 2);
 	  if (j < 0)
 	    val[i] = 0;
 	  else
-	    {
-	      val[i] = r->sig[j];
-	      unsigned HOST_WIDE_INT v = val[i];
-	      v <<= HOST_BITS_PER_LONG;
-	      val[i] = v;
-	      val[i] |= r->sig[j - 1];
-	    }
+	    val[i] = r->sig[j];
+	  j += 1;
+	  if (j >= 0)
+	    val[i] |= (unsigned HOST_WIDE_INT) r->sig[j] << HOST_BITS_PER_LONG;
 	}
 #endif
-      w = SIGSZ * HOST_BITS_PER_LONG + words * HOST_BITS_PER_WIDE_INT;
-      tmp = real_int::from_array
-	(val, (w + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT, w);
-      tmp = wi::lrshift (tmp, (words * HOST_BITS_PER_WIDE_INT) - exp);
-      result = wide_int::from (tmp, precision, UNSIGNED);
+      /* Shift the value into place and truncate to the desired precision.  */
+      result = wide_int::from_array (val, words, w);
+      result = wi::lrshift (result, w - exp);
+      result = wide_int::from (result, precision, UNSIGNED);
 
       if (r->sign)
 	return -result;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]