dwarf2out: For ppc64le IEEE quad long double, use DW_ATE_GNU_*float128 [PR104194]

Message ID 20220124193439.GV2646553@tucnak
State New
Headers
Series dwarf2out: For ppc64le IEEE quad long double, use DW_ATE_GNU_*float128 [PR104194] |

Commit Message

Jakub Jelinek Jan. 24, 2022, 7:34 p.m. UTC
  Hi!

As mentioned in the PR, we emit the same
        .uleb128 0x3     # (DIE (0x42) DW_TAG_base_type)
        .byte   0x10     # DW_AT_byte_size
        .byte   0x4      # DW_AT_encoding
        .4byte  .LASF2   # DW_AT_name: "long double"
(0x4 is DW_ATE_float) whether we on powerpc64le-linux use
-mabi=ibmlongdouble or -mabi=ieeelongdouble.
http://lists.dwarfstd.org/pipermail/dwarf-discuss-dwarfstd.org/2022-January/004859.html
lists some options how to handle that and Ulrich mentioned it in his
Cauldron talk too:
https://slideslive.com/38902369/precise-target-floatingpoint-emulation-in-gdb?ref=account-folder-9307-folders
pages 8-16.

The following patch uses DW_ATE_GNU_{,complex_}float128 (new extensions
equal to corresponding HP extensions) instead of DW_ATE_float,
another possibility would be DW_ATE_GNU_precision attribute on the
DW_TAG_base_type that would for these multiple 16-byte float cases
(or always) emit a precision (113 for binary128, 106 for double double),
yet another one is what Ulrich mentions in his slides
(DW_AT_GNU_encoding_variant {0,1}).

I didn't get any responses to my dwarf discuss mails yet, on IRC
Jason preferred a DW_AT_encoding change while Mark prefered
DW_AT_GNU_precision.  In any case, all of these are just GNU extensions,
if/when DWARF standardizes something else, we can use it for -gdwarf-6
or later.

Bootstrap/regtest pending on powerpc64le-linux (both defaulting to
ibmlongdouble and ieeelongdouble), ok for trunk if it passes?

2022-01-24  Jakub Jelinek  <jakub@redhat.com>

	PR debug/104194
	* dwarf2.def (DW_ATE_GNU_float128, DW_ATE_GNU_complex_float128): New
	DW_AT_encoding values.

	* dwarf2out.c (base_type_die): Use DW_ATE_GNU_float128 instead of
	DW_ATE_float for 16-byte non-composite mode if target supports also
	composite modes.  Similarly use DW_AT_GNU_complex_float128 instead
	of DW_ATE_complex_float for 32-byte complex mode with non-composite
	inner mode if target supports also composite modes.


	Jakub
  

Comments

Mark Wielaard Jan. 24, 2022, 10:14 p.m. UTC | #1
Hi,

On Mon, Jan 24, 2022 at 08:34:39PM +0100, Jakub Jelinek wrote:
> The following patch uses DW_ATE_GNU_{,complex_}float128 (new extensions
> equal to corresponding HP extensions) instead of DW_ATE_float,
> another possibility would be DW_ATE_GNU_precision attribute on the
> DW_TAG_base_type that would for these multiple 16-byte float cases
> (or always) emit a precision (113 for binary128, 106 for double double),
> yet another one is what Ulrich mentions in his slides
> (DW_AT_GNU_encoding_variant {0,1}).
> 
> I didn't get any responses to my dwarf discuss mails yet, on IRC
> Jason preferred a DW_AT_encoding change while Mark prefered
> DW_AT_GNU_precision.  In any case, all of these are just GNU extensions,
> if/when DWARF standardizes something else, we can use it for -gdwarf-6
> or later.

When we try to standardize this (in DWARF6) then I think I prefer
having a separate attribute which specifies the precision, just like
we already use DW_AT_byte_size to specify the size. That might also
help with the different float16 encodings.

But if we need a solution now (for gcc12) then using a new DW_ATE_GNU
extension seems more practical.

Cheers,

Mark
  
Jakub Jelinek Jan. 24, 2022, 10:26 p.m. UTC | #2
On Mon, Jan 24, 2022 at 11:14:41PM +0100, Mark Wielaard wrote:
> On Mon, Jan 24, 2022 at 08:34:39PM +0100, Jakub Jelinek wrote:
> > The following patch uses DW_ATE_GNU_{,complex_}float128 (new extensions
> > equal to corresponding HP extensions) instead of DW_ATE_float,
> > another possibility would be DW_ATE_GNU_precision attribute on the
> > DW_TAG_base_type that would for these multiple 16-byte float cases
> > (or always) emit a precision (113 for binary128, 106 for double double),
> > yet another one is what Ulrich mentions in his slides
> > (DW_AT_GNU_encoding_variant {0,1}).
> > 
> > I didn't get any responses to my dwarf discuss mails yet, on IRC
> > Jason preferred a DW_AT_encoding change while Mark prefered
> > DW_AT_GNU_precision.  In any case, all of these are just GNU extensions,
> > if/when DWARF standardizes something else, we can use it for -gdwarf-6
> > or later.
> 
> When we try to standardize this (in DWARF6) then I think I prefer
> having a separate attribute which specifies the precision, just like
> we already use DW_AT_byte_size to specify the size. That might also
> help with the different float16 encodings.
> 
> But if we need a solution now (for gcc12) then using a new DW_ATE_GNU
> extension seems more practical.

Actually for debuggers, DW_AT_GNU_precision might be better.
I think debuggers will just give up on unknown DW_ATE_*, they really don't
know how to handle it.
While if they see an unknown attribute on the base type, I'd think they'd
ignore it, so treat the IEEE quad "long double" as IBM double double
instead, but e.g. for __float128 or __ibm128 would be using the DW_AT_name
heuristics handled fine.
Yet another short term solution might be not use DW_TAG_base_type
for the IEEE quad long double, but instead pretend it is a DW_TAG_typedef
with DW_AT_name "long double" to __float128 DW_TAG_base_type.
I bet gdb would even handle it without any changes, but of course, it would
be larger than the other proposed changes.

	Jakub
  

Patch

--- include/dwarf2.def.jj	2022-01-11 23:11:23.593273249 +0100
+++ include/dwarf2.def	2022-01-24 17:46:08.699138085 +0100
@@ -732,11 +732,20 @@  DW_ATE (DW_ATE_ASCII, 0x12)
 DW_ATE_DUP (DW_ATE_lo_user, 0x80)
 DW_ATE_DUP (DW_ATE_hi_user, 0xff)
 
+/* GNU extensions.  */
+DW_ATE (DW_ATE_GNU_float128, 0x82) /* Floating-point (IEEE quad precision if
+				      there are multiple 16-byte floating
+				      formats).  */
+DW_ATE (DW_ATE_GNU_complex_float128, 0x83) /* Complex fp
+					      (IEEE quad precision if there
+					       are multiple 16-byte floating
+					       formats).  */
+
 /* HP extensions.  */
 DW_ATE (DW_ATE_HP_float80, 0x80) /* Floating-point (80 bit).  */
 DW_ATE (DW_ATE_HP_complex_float80, 0x81) /* Complex floating-point (80 bit).  */
-DW_ATE (DW_ATE_HP_float128, 0x82) /* Floating-point (128 bit).  */
-DW_ATE (DW_ATE_HP_complex_float128, 0x83) /* Complex fp (128 bit).  */
+DW_ATE_DUP (DW_ATE_HP_float128, 0x82) /* Floating-point (128 bit).  */
+DW_ATE_DUP (DW_ATE_HP_complex_float128, 0x83) /* Complex fp (128 bit).  */
 DW_ATE (DW_ATE_HP_floathpintel, 0x84) /* Floating-point (82 bit IA64).  */
 DW_ATE (DW_ATE_HP_imaginary_float80, 0x85)
 DW_ATE (DW_ATE_HP_imaginary_float128, 0x86)
--- gcc/dwarf2out.cc.jj	2022-01-20 11:58:12.632304188 +0100
+++ gcc/dwarf2out.cc	2022-01-24 18:27:12.862642858 +0100
@@ -13260,7 +13260,23 @@  base_type_die (tree type, bool reverse)
 	    encoding = DW_ATE_lo_user;
 	}
       else
-	encoding = DW_ATE_float;
+	{
+	  encoding = DW_ATE_float;
+
+	  /* On targets like PowerPC which support both
+	     a double double 16-byte floating mode
+	     (MODE_COMPOSITE_P) and some other 16-byte
+	     floating mode (IEEE quad precision), use
+	     DW_ATE_GNU_float128 instead of DW_ATE_float
+	     for the latter.  */
+	  machine_mode mode;
+	  if (known_eq (GET_MODE_SIZE (TYPE_MODE (type)), 16)
+	      && !MODE_COMPOSITE_P (TYPE_MODE (type)))
+	    FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
+	      if (known_eq (GET_MODE_SIZE (mode), 16)
+		  && MODE_COMPOSITE_P (mode))
+		encoding = DW_ATE_GNU_float128;
+	}
       break;
 
     case FIXED_POINT_TYPE:
@@ -13276,7 +13292,23 @@  base_type_die (tree type, bool reverse)
 	 a user defined type for it.  */
     case COMPLEX_TYPE:
       if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
-	encoding = DW_ATE_complex_float;
+	{
+	  encoding = DW_ATE_complex_float;
+
+	  /* On targets like PowerPC which support both
+	     a double double 16-byte floating mode
+	     (MODE_COMPOSITE_P) and some other 16-byte
+	     floating mode (IEEE quad precision), use
+	     DW_ATE_GNU_complex_float128 instead of
+	     DW_ATE_float for the latter.  */
+	  machine_mode mode;
+	  if (known_eq (GET_MODE_SIZE (TYPE_MODE (type)), 32)
+	      && !MODE_COMPOSITE_P (TYPE_MODE (TREE_TYPE (type))))
+	    FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
+	      if (known_eq (GET_MODE_SIZE (mode), 16)
+		  && MODE_COMPOSITE_P (mode))
+		encoding = DW_ATE_GNU_complex_float128;
+	}
       else
 	encoding = DW_ATE_lo_user;
       break;