This is the mail archive of the gcc-patches@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]

[Fortran] PR 34482: RFC and patch: BOZ to real/complex conversion for some systems


Assume for the following that 4 is the default integer/real kind and 8
the largest integer kind. In DATA
    z'FFFFFFFF'
is has the largest integer kind and is thus identically to
    z'00000000FFFFFFFF'
If one now transfers this to a default-kind real, i.e.
    real(z'FFFFFFFF')
one transfers an 8 to a 4 byte variable. Depending on the system only
the zeros (00000000) or the ones (FFFFFFFF) are transferred.

I think everyone would expect in this case that the ones/FFFFFFFF are
bit-wise transferred, which the attached patch does by converting the
BOZ to the smallest possible kind; for the example this is 4. This fixes
the PR.


However, I am not sure it does the right thing on all systems for:
    real(z'00000000FFFFFFFF',kind=8)
If one converts this to kind 4 ("z'FFFFFFFF'") and transfers it then,
one might get FFFFFFFF00000000 on some sytems instead of
00000000FFFFFFFF. -- Or not?

Jerry, can you check that the patch does the right thing on such
platforms and  real(z'00000000FFFFFFFF',kind=8) ?


The attached patch has been built and regression tested on x86-64-linux.
It has also been tested by Jerry for nan_4.f90 on a PowerPC.

If it does not have the issue I outlined above: OK for the trunk?

If it does, one needs to store the number of bits including significant
prefixing zeros. Or should one use MAX(boz_bit_size, lhs_bit_size)? 
(The result of the two conversions is not the same!)

I think the Fortran standard does not say at all what is supposed to
happen here. (For integer, gfortran simply assigns the integer and the
conversion to integer is done via GMP; thus  z'00000000FFFFFFFF' and
z'FFFFFFFF' are equivalent.)

Tobias
2007-12-17  Tobias Burnus  <burnus@net-b.de>

	PR fortran/34482
	* target-memory.c (gfc_convert_boz): Change BOZ kind to
	smallest integer before converting.

Index: gcc/fortran/target-memory.c
===================================================================
--- gcc/fortran/target-memory.c	(Revision 131004)
+++ gcc/fortran/target-memory.c	(Arbeitskopie)
@@ -596,10 +596,12 @@
   return len;
 }
 
+
 void
 gfc_convert_boz (gfc_expr *expr, gfc_typespec *ts)
 {
-  size_t buffer_size;
+  size_t buffer_size, boz_bit_size;
+  int index;
   unsigned char *buffer;
 
   if (!expr->is_boz)
@@ -616,6 +618,16 @@
   else
     return;
 
+  /* Convert BOZ to the smallest possible integer kind.  */
+  boz_bit_size = mpz_sizeinbase (expr->value.integer, 2);
+  for (index = 0; gfc_integer_kinds[index].kind != 0; ++index)
+    {
+	if ((unsigned) gfc_integer_kinds[index].bit_size >= boz_bit_size)
+	  break;
+    }
+  gcc_assert(gfc_integer_kinds[index].radix == 2);
+  expr->ts.kind = gfc_integer_kinds[index].kind;
+
   buffer_size = MAX (buffer_size, size_integer (expr->ts.kind));
 
   buffer = (unsigned char*)alloca (buffer_size);

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