]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Prepare vfprintf to use __printf_fp/__printf_fphex with float128 arg
authorGabriel F. T. Gomes <gabrielftg@linux.ibm.com>
Thu, 27 Jun 2019 20:43:44 +0000 (17:43 -0300)
committerGabriel F. T. Gomes <gabrielftg@linux.ibm.com>
Thu, 27 Jun 2019 20:51:59 +0000 (17:51 -0300)
On powerpc64le, long double can currently take two formats: the same as
double (-mlong-double-64) or IBM Extended Precision (default with
-mlong-double-128 or explicitly with -mabi=ibmlongdouble).  The internal
implementation of printf-like functions is aware of these possibilities
and properly parses floating-point values from the variable arguments,
before making calls to __printf_fp and __printf_fphex.  These functions
are also aware of the format possibilities and know how to convert both
formats to string.

When library support for TS 18661-3 was added to glibc, __printf_fp and
__printf_fphex were extended with support for an additional type
(__float128/_Float128) with a different format (binary128).  Now that
powerpc64le is getting support for its third long double format, and
taking into account that this format is the same as the format of
__float128/_Float128, this patch extends __vfprintf_internal to properly
call __printf_fp and __printf_fphex with this new format.

Tested for powerpc64le (with additional patches to actually enable the
use of these preparations) and for x86_64.

Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
ChangeLog
libio/libioP.h
stdio-common/printf-parse.h
stdio-common/vfprintf-internal.c

index 306c942a45817fb497356eea9e3dfebbd8ed4537..24057036a47eab7ca819e14d09f307899c3d8f02 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2019-06-27  Gabriel F. T. Gomes  <gabrielftg@linux.ibm.com>
+
+       * libio/libioP.h (PRINTF_LDBL_USES_FLOAT128): New macro to be
+       used as a mask for the mode argument of __vfprintf_internal.
+       * stdio-common/printf-parse.h (printf_arg): New union member:
+       pa_float128.
+       * stdio-common/vfprintf-internal.c
+       (PARSE_FLOAT_VA_ARG_EXTENDED): New macro.
+       (PARSE_FLOAT_VA_ARG): Likewise.
+       (SETUP_FLOAT128_INFO): Likewise.
+       (process_arg): Use PARSE_FLOAT_VA_ARG_EXTENDED and
+       SETUP_FLOAT128_INFO.
+       [__HAVE_FLOAT128_UNLIKE_LDBL] (printf_positional): Write
+       floating-point value to the new union member, pa_float128.
+       (printf_positional): Zero-initialize args_value[cnt] with memset.
+
 2019-06-27  Florian Weimer  <fweimer@redhat.com>
 
        [BZ #24740]
index afa46cc5194189052ef2cba4ac4531c4607be7bb..8db24e1861c69eb214cc17ececb7b056671ac18a 100644 (file)
@@ -712,10 +712,22 @@ extern int __vswprintf_internal (wchar_t *string, size_t maxlen,
    defined to 1 or 2.  Otherwise, such checks are ignored.
 
    PRINTF_CHK indicates, to the internal function being called, that the
-   call is originated from one of the __*printf_chk functions.  */
-#define PRINTF_LDBL_IS_DBL 0x0001
-#define PRINTF_FORTIFY     0x0002
-#define PRINTF_CHK        0x0004
+   call is originated from one of the __*printf_chk functions.
+
+   PRINTF_LDBL_USES_FLOAT128 is used on platforms where the long double
+   format used to be different from the IEC 60559 double format *and*
+   also different from the Quadruple 128-bits IEC 60559 format (such as
+   the IBM Extended Precision format on powerpc or the 80-bits IEC 60559
+   format on x86), but was later converted to the Quadruple 128-bits IEC
+   60559 format, which is the same format that the _Float128 always has
+   (hence the `USES_FLOAT128' suffix in the name of the flag).  When set
+   to one, this macro indicates that long double values are to be
+   handled as having this new format.  Otherwise, they should be handled
+   as the previous format on that platform.  */
+#define PRINTF_LDBL_IS_DBL             0x0001
+#define PRINTF_FORTIFY                 0x0002
+#define PRINTF_CHK                     0x0004
+#define PRINTF_LDBL_USES_FLOAT128      0x0008
 
 extern size_t _IO_getline (FILE *,char *, size_t, int, int);
 libc_hidden_proto (_IO_getline)
index 397508638dad4ec0b3ef426c3d4f212d4eeed0b7..00f3280b8a12a7d61dd1bff73ddb0bc0e805591f 100644 (file)
@@ -57,6 +57,9 @@ union printf_arg
     unsigned long long int pa_u_long_long_int;
     double pa_double;
     long double pa_long_double;
+#if __HAVE_FLOAT128_UNLIKE_LDBL
+    _Float128 pa_float128;
+#endif
     const char *pa_string;
     const wchar_t *pa_wstring;
     void *pa_pointer;
index ead2b04cb96b0346dde876e5d41418fae2cc8b0d..d9dca78fc6f0a6e857c466406bbe1f99db2d04fc 100644 (file)
     } while (0)
 #define UNBUFFERED_P(S) ((S)->_flags & _IO_UNBUFFERED)
 
+#if __HAVE_FLOAT128_UNLIKE_LDBL
+# define PARSE_FLOAT_VA_ARG_EXTENDED(INFO)                                   \
+  do                                                                         \
+    {                                                                        \
+      if (is_long_double                                                     \
+         && (mode_flags & PRINTF_LDBL_USES_FLOAT128) != 0)                   \
+       {                                                                     \
+         INFO.is_binary128 = 1;                                              \
+         the_arg.pa_float128 = va_arg (ap, _Float128);                       \
+       }                                                                     \
+      else                                                                   \
+       {                                                                     \
+         PARSE_FLOAT_VA_ARG (INFO);                                          \
+       }                                                                     \
+    }                                                                        \
+  while (0)
+#else
+# define PARSE_FLOAT_VA_ARG_EXTENDED(INFO)                                   \
+  PARSE_FLOAT_VA_ARG (INFO);
+#endif
+
+#define PARSE_FLOAT_VA_ARG(INFO)                                             \
+  do                                                                         \
+    {                                                                        \
+      INFO.is_binary128 = 0;                                                 \
+      if (is_long_double)                                                    \
+       the_arg.pa_long_double = va_arg (ap, long double);                    \
+      else                                                                   \
+       the_arg.pa_double = va_arg (ap, double);                              \
+    }                                                                        \
+  while (0)
+
+#if __HAVE_FLOAT128_UNLIKE_LDBL
+# define SETUP_FLOAT128_INFO(INFO)                                           \
+  do                                                                         \
+    {                                                                        \
+      if ((mode_flags & PRINTF_LDBL_USES_FLOAT128) != 0)                     \
+       INFO.is_binary128 = is_long_double;                                   \
+      else                                                                   \
+       INFO.is_binary128 = 0;                                                \
+    }                                                                        \
+  while (0)
+#else
+# define SETUP_FLOAT128_INFO(INFO)                                           \
+  do                                                                         \
+    {                                                                        \
+      INFO.is_binary128 = 0;                                                 \
+    }                                                                        \
+  while (0)
+#endif
+
 #define done_add(val) \
   do {                                                                       \
     unsigned int _val = val;                                                 \
@@ -771,10 +822,7 @@ static const uint8_t jump_table[] =
                                        .wide = sizeof (CHAR_T) != 1,         \
                                        .is_binary128 = 0};                   \
                                                                              \
-           if (is_long_double)                                               \
-             the_arg.pa_long_double = va_arg (ap, long double);              \
-           else                                                              \
-             the_arg.pa_double = va_arg (ap, double);                        \
+           PARSE_FLOAT_VA_ARG_EXTENDED (info);                               \
            ptr = (const void *) &the_arg;                                    \
                                                                              \
            function_done = __printf_fp (s, &info, &ptr);                     \
@@ -787,8 +835,7 @@ static const uint8_t jump_table[] =
                fspec->data_arg_type = PA_DOUBLE;                             \
                fspec->info.is_long_double = 0;                               \
              }                                                               \
-           /* Not supported by *printf functions.  */                        \
-           fspec->info.is_binary128 = 0;                                     \
+           SETUP_FLOAT128_INFO (fspec->info);                                \
                                                                              \
            function_done = __printf_fp (s, &fspec->info, &ptr);              \
          }                                                                   \
@@ -831,10 +878,7 @@ static const uint8_t jump_table[] =
                                        .wide = sizeof (CHAR_T) != 1,         \
                                        .is_binary128 = 0};                   \
                                                                              \
-           if (is_long_double)                                               \
-             the_arg.pa_long_double = va_arg (ap, long double);              \
-           else                                                              \
-             the_arg.pa_double = va_arg (ap, double);                        \
+           PARSE_FLOAT_VA_ARG_EXTENDED (info);                               \
            ptr = (const void *) &the_arg;                                    \
                                                                              \
            function_done = __printf_fphex (s, &info, &ptr);                  \
@@ -844,8 +888,7 @@ static const uint8_t jump_table[] =
            ptr = (const void *) &args_value[fspec->data_arg];                \
            if (__glibc_unlikely ((mode_flags & PRINTF_LDBL_IS_DBL) != 0))    \
              fspec->info.is_long_double = 0;                                 \
-           /* Not supported by *printf functions.  */                        \
-           fspec->info.is_binary128 = 0;                                     \
+           SETUP_FLOAT128_INFO (fspec->info);                                \
                                                                              \
            function_done = __printf_fphex (s, &fspec->info, &ptr);           \
          }                                                                   \
@@ -1869,6 +1912,10 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
            args_value[cnt].pa_double = va_arg (*ap_savep, double);
            args_type[cnt] &= ~PA_FLAG_LONG_DOUBLE;
          }
+#if __HAVE_FLOAT128_UNLIKE_LDBL
+       else if ((mode_flags & PRINTF_LDBL_USES_FLOAT128) != 0)
+         args_value[cnt].pa_float128 = va_arg (*ap_savep, _Float128);
+#endif
        else
          args_value[cnt].pa_long_double = va_arg (*ap_savep, long double);
        break;
@@ -1887,7 +1934,7 @@ printf_positional (FILE *s, const CHAR_T *format, int readonly_format,
              (args_value[cnt].pa_user, ap_savep);
          }
        else
-         args_value[cnt].pa_long_double = 0.0;
+         memset (&args_value[cnt], 0, sizeof (args_value[cnt]));
        break;
       case -1:
        /* Error case.  Not all parameters appear in N$ format