Patchwork RFC [MIPS, RS6000] Mangling of IBM long double template literals

login
register
mail settings
Submitter Alan Modra
Date June 12, 2013, 3:13 p.m.
Message ID <20130612151349.GB21523@bubble.grove.modra.org>
Download mbox | patch
Permalink /patch/250809/
State New
Headers show

Comments

Alan Modra - June 12, 2013, 3:13 p.m.
As noted in the comment below, IBM long double is really an array of
two doubles.  In little-endian mode this means the words of each
double should be reversed in write_real_cst, but the large magnitude
double remains the first element of the array.

This patch specially treats IBM long double so that mangling for
template literal args of a given long double value is the same for
both little and big endian.  Bootstrapped etc. powerpc64-linux.

This is of course an ABI change for any existing little-endian users
of IBM long double literals in templates.  On powerpc, I think we can
safely say there are no such users.  However it does look like MIPS
also uses a variant of IBM long double, and I'm less certain there.

	* mangle.c (write_real_cst): Specially treat IBM long double.
Joseph S. Myers - June 12, 2013, 6:16 p.m.
On Thu, 13 Jun 2013, Alan Modra wrote:

> This is of course an ABI change for any existing little-endian users
> of IBM long double literals in templates.  On powerpc, I think we can
> safely say there are no such users.  However it does look like MIPS
> also uses a variant of IBM long double, and I'm less certain there.

That variant was used for IRIX, for which support was removed over a year 
ago.  It would be good to remove the code that I noted in 
<http://gcc.gnu.org/ml/gcc-patches/2012-03/msg00819.html> was thereby made 
obsolete.
Richard Sandiford - June 12, 2013, 9:06 p.m.
"Joseph S. Myers" <joseph@codesourcery.com> writes:
> On Thu, 13 Jun 2013, Alan Modra wrote:
>> This is of course an ABI change for any existing little-endian users
>> of IBM long double literals in templates.  On powerpc, I think we can
>> safely say there are no such users.  However it does look like MIPS
>> also uses a variant of IBM long double, and I'm less certain there.
>
> That variant was used for IRIX, for which support was removed over a year 
> ago.  It would be good to remove the code that I noted in 
> <http://gcc.gnu.org/ml/gcc-patches/2012-03/msg00819.html> was thereby made 
> obsolete.

OK, I'll try to do that sometime.  And as far as this change goes,
IRIX was big-endian only anyway, so it wouldn't have been affected.
Thanks Alan for checking though.

Richard
Alan Modra - Nov. 12, 2013, 10:19 p.m.
Ping this patch:
http://gcc.gnu.org/ml/gcc-patches/2013-06/msg00686.html

Patch

Index: gcc/cp/mangle.c
===================================================================
--- gcc/cp/mangle.c	(revision 199975)
+++ gcc/cp/mangle.c	(working copy)
@@ -1591,28 +1591,35 @@  write_real_cst (const tree value)
 {
   if (abi_version_at_least (2))
     {
+      const struct real_format *fmt;
       long target_real[4];  /* largest supported float */
       char buffer[9];       /* eight hex digits in a 32-bit number */
-      int i, limit, dir;
+      int i, limit, dir, twid;
 
       tree type = TREE_TYPE (value);
       int words = GET_MODE_BITSIZE (TYPE_MODE (type)) / 32;
 
-      real_to_target (target_real, &TREE_REAL_CST (value),
-		      TYPE_MODE (type));
+      fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
+      real_to_target_fmt (target_real, &TREE_REAL_CST (value), fmt);
 
       /* The value in target_real is in the target word order,
 	 so we must write it out backward if that happens to be
 	 little-endian.  write_number cannot be used, it will
 	 produce uppercase.  */
       if (FLOAT_WORDS_BIG_ENDIAN)
-	i = 0, limit = words, dir = 1;
+	i = 0, limit = words, dir = 1, twid = 0;
+      else if (fmt->pnan < fmt->p)
+	/* This is an IBM extended double format made up of two IEEE
+	   doubles.  When little-endian, the doubles are in
+	   little-endian word order, but the array order stays the
+	   same.  */
+	i = 0, limit = words, dir = 1, twid = 1;
       else
-	i = words - 1, limit = -1, dir = -1;
+	i = words - 1, limit = -1, dir = -1, twid = 0;
 
       for (; i != limit; i += dir)
 	{
-	  sprintf (buffer, "%08lx", (unsigned long) target_real[i]);
+	  sprintf (buffer, "%08lx", (unsigned long) target_real[i ^ twid]);
 	  write_chars (buffer, 8);
 	}
     }