diff mbox

DWARF: make signedness explicit for enumerator const values

Message ID 21ef1b1d-ca1e-4881-c51a-e48ee046ea68@adacore.com
State New
Headers show

Commit Message

Pierre-Marie de Rodat Dec. 9, 2016, 11:59 a.m. UTC
On 11/18/2016 06:22 PM, Pierre-Marie de Rodat wrote:
> I agree with you, so I’ll revise to instead add a DW_AT_type attribute

> to enumeration DIEs to point to a base type.


Here is the patch to implement this. Bootstrapped and regtested (GCC’s 
testsuite) successfuly on x86_64-linux.

However, it is important to note that this creates a regression in GDB: 
in Ada, “ptype” of an array whose bounds are a subrange of an 
enumeration type gives something like:

     array (0 .. 10) of integer

instead of the expected:

     array (first_value .. last_value) of integer

We, at AdaCore, have a candidate GDB patch to fix this regression, but 
even if it gets upstream, this will affect all existing GDB versions. No 
other GDB regression otherwise.

-- 
Pierre-Marie de Rodat

Comments

Mark Wielaard Dec. 9, 2016, 1 p.m. UTC | #1
On Fri, 2016-12-09 at 12:59 +0100, Pierre-Marie de Rodat wrote:
> There seems to be only two legal DWARF alternatives to solve this issue:

> one is to add a DW_AT_type attribute to DW_TAG_enumerator_type DIEs to

> make it point to a base type that specifies the signedness.  The other

> is to make sure the form of the DW_AT_const_value attribute carries the

> signedness information.


BTW. I think it should also be possible to simply attach a
DW_AT_encoding directly to the DW_TAG_enumeration_type. It seems a
simple oversight that option isn't listed in the current DWARF spec.

I filed an issue about it:
http://dwarfstd.org/ShowIssue.php?issue=161130.2
I haven't heard back from the committee. But Todd Allen from Concurrent
said their Ada compiler already does this when generating DWARF

Cheers,

Mark
Pierre-Marie de Rodat Dec. 9, 2016, 1:38 p.m. UTC | #2
On 12/09/2016 02:00 PM, Mark Wielaard wrote:
> BTW. I think it should also be possible to simply attach a

> DW_AT_encoding directly to the DW_TAG_enumeration_type. It seems a

> simple oversight that option isn't listed in the current DWARF spec.

>

> I filed an issue about it:

> http://dwarfstd.org/ShowIssue.php?issue=161130.2

> I haven't heard back from the committee. But Todd Allen from Concurrent

> said their Ada compiler already does this when generating DWARF


Yes, thank you for opening this issue. :-)

Hm… I’m not comfortable with attaching a DW_AT_encoding on 
DW_TAG_enumeration_type DIE’s because this association is not listed in 
appendix A (Attributes by Tag Value). Now, this appendix is only 
informative, so doing so would not be a violation of the standard, I 
guess. Do you think we would need to protect this association with 
!dwarf_strict?

At this point I’m fine with all options, it’s just that I’m not 
confident enough that it will be fine for DWARF consumers.

-- 
Pierre-Marie de Rodat
Jason Merrill Dec. 9, 2016, 2:06 p.m. UTC | #3
On Fri, Dec 9, 2016 at 8:38 AM, Pierre-Marie de Rodat
<derodat@adacore.com> wrote:
> On 12/09/2016 02:00 PM, Mark Wielaard wrote:

>>

>> BTW. I think it should also be possible to simply attach a

>> DW_AT_encoding directly to the DW_TAG_enumeration_type. It seems a

>> simple oversight that option isn't listed in the current DWARF spec.

>>

>> I filed an issue about it:

>> http://dwarfstd.org/ShowIssue.php?issue=161130.2

>> I haven't heard back from the committee. But Todd Allen from Concurrent

>> said their Ada compiler already does this when generating DWARF

>

> Yes, thank you for opening this issue. :-)

>

> Hm… I’m not comfortable with attaching a DW_AT_encoding on

> DW_TAG_enumeration_type DIE’s because this association is not listed in

> appendix A (Attributes by Tag Value). Now, this appendix is only

> informative, so doing so would not be a violation of the standard, I guess.

> Do you think we would need to protect this association with !dwarf_strict?

>

> At this point I’m fine with all options, it’s just that I’m not confident

> enough that it will be fine for DWARF consumers.


I think it's fine guarded by !dwarf_strict; most consumers should
happily ignore it if they don't know what to do with it.

Jason
diff mbox

Patch

From bcc76900bdc0ec96d96a0a6290a3c21d1444e61b Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Fri, 9 Dec 2016 12:13:50 +0100
Subject: [PATCH] Ada/DWARF: add a DW_AT_type attribute to
 DW_TAG_enumeration_type

Currently, the DWARF description does not specify the signedness of the
representation of enumeration types.  This is a problem in some
contexts where DWARF consumers need to determine if value X is greater
than value Y.

For instance in Ada:

    type Enum_Type is ( A, B, C, D);
    for Enum_Type use (-1, 0, 1, 2);

    type Rec_Type (E : Enum_Type) is record
       when A .. B => null;
       when others => B : Booleann;
    end record;

The above can be described in DWARF the following way:

    DW_TAG_enumeration_type(Enum_Type)
    | DW_AT_byte_size: 1
      DW_TAG_enumerator(A)
      | DW_AT_const_value: -1
      DW_TAG_enumerator(B)
      | DW_AT_const_value: 0
      DW_TAG_enumerator(C)
      | DW_AT_const_value: 1
      DW_TAG_enumerator(D)
      | DW_AT_const_value: 2

    DW_TAG_structure_type(Rec_Type)
      DW_TAG_member(E)
      | DW_AT_type: <Enum_Type>
      DW_TAG_variant_part
      | DW_AT_discr: <E>
        DW_TAG_variant
        | DW_AT_discr_list: DW_DSC_range 0x7f 0
        DW_TAG_variant
        | DW_TAG_member(b)

DWARF consumers need to know that enumerators (A, B, C and D) are signed
in order to determine the set of E values for which Rec_Type has a B
field.  In practice, they need to know how to interpret the 0x7f LEB128
number above (-1, not 127).

There seems to be only two legal DWARF alternatives to solve this issue:
one is to add a DW_AT_type attribute to DW_TAG_enumerator_type DIEs to
make it point to a base type that specifies the signedness.  The other
is to make sure the form of the DW_AT_const_value attribute carries the
signedness information.

The first alternative is valid only starting with DWARF3. The second
alternative is valid will all versions of the DWARF standard, however it
removes the size information embedded in the form used to encode
DW_AT_const_value attributes (DW_FORM_data8/16/32).

This patch implements the first alternative.

gcc/

	* dwarf2out.h (gen_enumeration_type_die): If the selected DWARF
	standard allows it, add a DW_AT_type attribute for the
	enum's TREE_TYPE, if any.

gcc/ada/

	* gcc-interface/decl.c (gnat_to_gnu_entity): Assign a base type
	to enumeration types.
	* gcc-interface/misc.c (gnat_get_array_descr_info): Don't strip
	types in the bounds subrange type's TREE_TYPE chain if they
	bring information about the kind of integral type involved.
	* gcc-interface/utils.c (make_type_from_size): Likewise for the
	base types involved.
---
 gcc/ada/gcc-interface/decl.c  |  4 ++++
 gcc/ada/gcc-interface/misc.c  |  6 ++++--
 gcc/ada/gcc-interface/utils.c | 12 +++++++++++-
 gcc/dwarf2out.c               |  4 ++++
 4 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c
index 9de85ef..961499d 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -1670,6 +1670,10 @@  gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, bool definition)
 	  if (!is_boolean)
 	    TYPE_VALUES (gnu_type) = nreverse (gnu_list);
 
+	  /* Provide a base type so that in debug info, the enumeration type
+	     has signedness information associated.  */
+	  TREE_TYPE (gnu_type) = gnat_type_for_size (esize, is_unsigned);
+
 	  /* Note that the bounds are updated at the end of this function
 	     to avoid an infinite recursion since they refer to the type.  */
 	  goto discrete_type;
diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 1fed72a..7eeec81 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -964,8 +964,10 @@  gnat_get_array_descr_info (const_tree const_type,
 	}
 
       /* The DWARF back-end will output BOUNDS_TYPE as the base type of
-	 the array index, so get to the base type of INDEX_TYPE.  */
-      while (TREE_TYPE (index_type))
+	 the array index.  All subtypes in the TREE_TYPE chain that just bring
+	 bounds can be ignored: strip them.  */
+      while (TREE_CODE (index_type) == INTEGER_TYPE
+	     && TREE_TYPE (index_type) != NULL_TREE)
 	index_type = TREE_TYPE (index_type);
 
       info->dimen[i].bounds_type = maybe_debug_type (index_type);
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index cde17fe..bd9a5a4 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -1136,7 +1136,17 @@  make_type_from_size (tree type, tree size_tree, bool for_biased)
 	new_type = make_unsigned_type (size);
       else
 	new_type = make_signed_type (size);
-      TREE_TYPE (new_type) = TREE_TYPE (type) ? TREE_TYPE (type) : type;
+
+      /* If TYPE is a special integral type (e.g. an ENUMERAL_TYPE) while
+	 TYPE's base type is an INTEGER_TYPE, we need to keep the information
+	 that NEW_TYPE is a special integral type as well.  So in this case,
+	 don't skip TYPE in the base type chain.  */
+      TREE_TYPE (new_type)
+	= (TREE_TYPE (type)
+	   && TREE_CODE (TREE_TYPE (type)) == TREE_CODE (type))
+	  ? TREE_TYPE (type)
+	  : type;
+
       SET_TYPE_RM_MIN_VALUE (new_type, TYPE_MIN_VALUE (type));
       SET_TYPE_RM_MAX_VALUE (new_type, TYPE_MAX_VALUE (type));
       /* Copy the name to show that it's essentially the same type and
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 8dc8523..a61f114 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -20923,6 +20923,10 @@  gen_enumeration_type_die (tree type, dw_die_ref context_die)
 			  scope_die_for (type, context_die), type);
       equate_type_number_to_die (type, type_die);
       add_name_attribute (type_die, type_tag (type));
+      if ((dwarf_version >= 3 || !dwarf_strict)
+	  && TREE_TYPE (type) != NULL_TREE)
+	add_type_attribute (type_die, TREE_TYPE (type), 0, TYPE_UNQUALIFIED,
+			    context_die);
       if (dwarf_version >= 4 || !dwarf_strict)
 	{
 	  if (ENUM_IS_SCOPED (type))
-- 
2.10.2