From bcc76900bdc0ec96d96a0a6290a3c21d1444e61b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat 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: DW_TAG_variant_part | DW_AT_discr: 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