]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix debug info for enumeration types with reverse Scalar_Storage_Order
authorEric Botcazou <ebotcazou@adacore.com>
Wed, 10 Jan 2024 12:23:46 +0000 (13:23 +0100)
committerEric Botcazou <ebotcazou@adacore.com>
Wed, 10 Jan 2024 12:27:24 +0000 (13:27 +0100)
This implements the support of DW_AT_endianity for enumeration types because
they are scalar and therefore, reverse Scalar_Storage_Order is supported for
them, but only when the -gstrict-dwarf switch is not passed because this is
an extension.

There is an associated GDB patch to be submitted to grok the new DWARF.

gcc/
* dwarf2out.cc (modified_type_die): Extend the support of reverse
storage order to enumeration types if -gstrict-dwarf is not passed.
(gen_enumeration_type_die): Add REVERSE parameter and generate the
DIE immediately after the existing one if it is true.
(gen_tagged_type_die): Add REVERSE parameter and pass it in the
call to gen_enumeration_type_die.
(gen_type_die_with_usage): Add REVERSE parameter and pass it in the
first recursive call as well as the call to gen_tagged_type_die.
(gen_type_die): Add REVERSE parameter and pass it in the call to
gen_type_die_with_usage.

gcc/dwarf2out.cc

index 2f9010bc3cbee78586d5403a8ed0e643b9f4bd41..1c994bb8b9b1e8599c38f4f0c8daba869a5d4957 100644 (file)
@@ -3940,7 +3940,7 @@ static void gen_descr_array_type_die (tree, struct array_descr_info *, dw_die_re
 #if 0
 static void gen_entry_point_die (tree, dw_die_ref);
 #endif
-static dw_die_ref gen_enumeration_type_die (tree, dw_die_ref);
+static dw_die_ref gen_enumeration_type_die (tree, dw_die_ref, bool);
 static dw_die_ref gen_formal_parameter_die (tree, tree, bool, dw_die_ref);
 static dw_die_ref gen_formal_parameter_pack_die  (tree, tree, dw_die_ref, tree*);
 static void gen_unspecified_parameters_die (tree, dw_die_ref);
@@ -3960,7 +3960,7 @@ static void gen_struct_or_union_type_die (tree, dw_die_ref,
                                                enum debug_info_usage);
 static void gen_subroutine_type_die (tree, dw_die_ref);
 static void gen_typedef_die (tree, dw_die_ref);
-static void gen_type_die (tree, dw_die_ref);
+static void gen_type_die (tree, dw_die_ref, bool = false);
 static void gen_block_die (tree, dw_die_ref);
 static void decls_for_scope (tree, dw_die_ref, bool = true);
 static bool is_naming_typedef_decl (const_tree);
@@ -3976,8 +3976,10 @@ static struct dwarf_file_data * lookup_filename (const char *);
 static void retry_incomplete_types (void);
 static void gen_type_die_for_member (tree, tree, dw_die_ref);
 static void gen_generic_params_dies (tree);
-static void gen_tagged_type_die (tree, dw_die_ref, enum debug_info_usage);
-static void gen_type_die_with_usage (tree, dw_die_ref, enum debug_info_usage);
+static void gen_tagged_type_die (tree, dw_die_ref, enum debug_info_usage,
+                                bool = false);
+static void gen_type_die_with_usage (tree, dw_die_ref, enum debug_info_usage,
+                                    bool = false);
 static void splice_child_die (dw_die_ref, dw_die_ref);
 static int file_info_cmp (const void *, const void *);
 static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *, var_loc_view,
@@ -13665,8 +13667,11 @@ modified_type_die (tree type, int cv_quals, bool reverse,
   const int cv_qual_mask = (TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE
                            | TYPE_QUAL_RESTRICT | TYPE_QUAL_ATOMIC | 
                            ENCODE_QUAL_ADDR_SPACE(~0U));
-  const bool reverse_base_type
-    = need_endianity_attribute_p (reverse) && is_base_type (type);
+  /* DW_AT_endianity is specified only for base types in the standard.  */
+  const bool reverse_type
+    = need_endianity_attribute_p (reverse)
+      && (is_base_type (type)
+         || (TREE_CODE (type) == ENUMERAL_TYPE && !dwarf_strict));
 
   if (code == ERROR_MARK)
     return NULL;
@@ -13726,9 +13731,9 @@ modified_type_die (tree type, int cv_quals, bool reverse,
 
       /* DW_AT_endianity doesn't come from a qualifier on the type, so it is
         dealt with specially: the DIE with the attribute, if it exists, is
-        placed immediately after the regular DIE for the same base type.  */
+        placed immediately after the regular DIE for the same type.  */
       if (mod_type_die
-         && (!reverse_base_type
+         && (!reverse_type
              || ((mod_type_die = mod_type_die->die_sib) != NULL
                  && get_AT_unsigned (mod_type_die, DW_AT_endianity))))
        return mod_type_die;
@@ -13745,7 +13750,7 @@ modified_type_die (tree type, int cv_quals, bool reverse,
       tree dtype = TREE_TYPE (name);
 
       /* Skip the typedef for base types with DW_AT_endianity, no big deal.  */
-      if (qualified_type == dtype && !reverse_base_type)
+      if (qualified_type == dtype && !reverse_type)
        {
          tree origin = decl_ultimate_origin (name);
 
@@ -13952,7 +13957,7 @@ modified_type_die (tree type, int cv_quals, bool reverse,
        mod_type_die = base_type_die (type, reverse);
 
       /* The DIE with DW_AT_endianity is placed right after the naked DIE.  */
-      if (reverse_base_type)
+      if (reverse_type)
        {
          dw_die_ref after_die
            = modified_type_die (type, cv_quals, false, context_die);
@@ -13965,6 +13970,17 @@ modified_type_die (tree type, int cv_quals, bool reverse,
     }
   else
     {
+      /* The DIE with DW_AT_endianity is placed right after the naked DIE.  */
+      if (reverse_type)
+       {
+         dw_die_ref after_die
+           = modified_type_die (type, cv_quals, false, context_die);
+         gen_type_die (type, context_die, true);
+         gcc_assert (after_die->die_sib
+                     && get_AT_unsigned (after_die->die_sib, DW_AT_endianity));
+         return after_die->die_sib;
+       }
+
       gen_type_die (type, context_die);
 
       /* We have to get the type_main_variant here (and pass that to the
@@ -14034,7 +14050,7 @@ modified_type_die (tree type, int cv_quals, bool reverse,
        }
     }
 
-  if (qualified_type && !reverse_base_type)
+  if (qualified_type && !reverse_type)
     equate_type_number_to_die (qualified_type, mod_type_die);
 
   if (item_type)
@@ -22824,19 +22840,31 @@ record_type_tag (tree type)
 /* Generate a DIE to represent an enumeration type.  Note that these DIEs
    include all of the information about the enumeration values also. Each
    enumerated type name/value is listed as a child of the enumerated type
-   DIE.  */
+   DIE. REVERSE is true if the type is to be interpreted in the reverse
+   storage order wrt the target order.  */
 
 static dw_die_ref
-gen_enumeration_type_die (tree type, dw_die_ref context_die)
+gen_enumeration_type_die (tree type, dw_die_ref context_die, bool reverse)
 {
   dw_die_ref type_die = lookup_type_die (type);
   dw_die_ref orig_type_die = type_die;
 
-  if (type_die == NULL)
+  if (type_die == NULL || reverse)
     {
-      type_die = new_die (DW_TAG_enumeration_type,
-                         scope_die_for (type, context_die), type);
-      equate_type_number_to_die (type, type_die);
+      /* The DIE with DW_AT_endianity is placed right after the naked DIE.  */
+      if (reverse)
+       {
+         gcc_assert (type_die);
+         dw_die_ref after_die = type_die;
+         type_die = new_die_raw (DW_TAG_enumeration_type);
+         add_child_die_after (context_die, type_die, after_die);
+       }
+      else
+       {
+         type_die = new_die (DW_TAG_enumeration_type,
+                             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 >= 4 || !dwarf_strict)
          && ENUM_IS_SCOPED (type))
@@ -22848,6 +22876,9 @@ gen_enumeration_type_die (tree type, dw_die_ref context_die)
                         TYPE_UNSIGNED (type)
                         ? DW_ATE_unsigned
                         : DW_ATE_signed);
+      if (reverse)
+       add_AT_unsigned (type_die, DW_AT_endianity,
+                        BYTES_BIG_ENDIAN ? DW_END_little : DW_END_big);
     }
   else if (! TYPE_SIZE (type) || ENUM_IS_OPAQUE (type))
     return type_die;
@@ -26155,7 +26186,8 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
 static void
 gen_tagged_type_die (tree type,
                     dw_die_ref context_die,
-                    enum debug_info_usage usage)
+                    enum debug_info_usage usage,
+                    bool reverse)
 {
   if (type == NULL_TREE
       || !is_tagged_type (type))
@@ -26200,8 +26232,8 @@ gen_tagged_type_die (tree type,
     {
       /* This might have been written out by the call to
         declare_in_namespace.  */
-      if (!TREE_ASM_WRITTEN (type))
-       gen_enumeration_type_die (type, context_die);
+      if (!TREE_ASM_WRITTEN (type) || reverse)
+       gen_enumeration_type_die (type, context_die, reverse);
     }
   else
     gen_struct_or_union_type_die (type, context_die, usage);
@@ -26215,7 +26247,7 @@ gen_tagged_type_die (tree type,
 
 static void
 gen_type_die_with_usage (tree type, dw_die_ref context_die,
-                        enum debug_info_usage usage)
+                        enum debug_info_usage usage, bool reverse)
 {
   struct array_descr_info info;
 
@@ -26279,7 +26311,7 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
 
       if (debug_type != NULL_TREE && debug_type != type)
        {
-         gen_type_die_with_usage (debug_type, context_die, usage);
+         gen_type_die_with_usage (debug_type, context_die, usage, reverse);
          return;
        }
     }
@@ -26326,7 +26358,7 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
        }
     }
 
-  if (TREE_ASM_WRITTEN (type))
+  if (TREE_ASM_WRITTEN (type) && !reverse)
     {
       /* Variable-length types may be incomplete even if
         TREE_ASM_WRITTEN.  For such types, fall through to
@@ -26398,7 +26430,7 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
-      gen_tagged_type_die (type, context_die, usage);
+      gen_tagged_type_die (type, context_die, usage, reverse);
       return;
 
     case VOID_TYPE:
@@ -26450,11 +26482,11 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
 }
 
 static void
-gen_type_die (tree type, dw_die_ref context_die)
+gen_type_die (tree type, dw_die_ref context_die, bool reverse)
 {
   if (type != error_mark_node)
     {
-      gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE);
+      gen_type_die_with_usage (type, context_die, DINFO_USAGE_DIR_USE, reverse);
       if (flag_checking)
        {
          dw_die_ref die = lookup_type_die (type);