public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Enhance array types debug info. for Ada
@ 2014-09-03  8:36 Pierre-Marie de Rodat
  2014-09-17 14:38 ` [PING] " Pierre-Marie de Rodat
  2014-10-03  9:19 ` [PATCH] " Jakub Jelinek
  0 siblings, 2 replies; 20+ messages in thread
From: Pierre-Marie de Rodat @ 2014-09-03  8:36 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 2796 bytes --]

Hi!

I'm currently working on improving the debug information output for GNAT 
(the Ada frontend in GCC), which currently uses non-standard DWARF to 
describe complex types. Lately, I focused on debug information for 
arrays and the attached inter-dependent patches are an attempt to do so:

   - they enhance the existing "array_descr_info" language hook;
   - they adjust the Fortran front-end accordingly (it's the only 
array_descr_info user currently);
   - they make the Ada front-end use this hook.

Here are more details about what motivated each patch:


  1. This first patch enhances the array_descr_info language hook so 
that front-end can pass more information about array types to the DWARF 
backend:

     - Array ordering (column/row major) so that the information that 
Fortran arrays are column major ordered comes from the Fortran front-end 
and so that later GNAT can decide itself for each array type (they can 
be both column and row major ordered).

     - Bounds type: Ada arrays can be indexed by integers but also 
characters, enumerated types, etc. However it seems that the middle-end 
makes the assumption that every array index is sizetype so this 
information is needed here for accurate debug info.

     It also makes the language hook generate "GNAT descriptive type" 
attributes for array types, just as the regular array types handling in 
dwarf2out.c does.

     Finally, it makes the DWARF back-end initialize the 
"array_descr_info" structure so that new fields can be added to it later 
without affecting existing front-ends that use this hook.


  2. Currently, this language hook is enabled only when (dwarf_version 
 >= 3 || !dwarf_strict). The hook generates information that is mostly 
valid for strict DWARFv2, though. The second patch enables this language 
hook every time and instead prevents the emission for some attributes 
when needed.


  3. This one enables the array_descr_info hook in GNAT.


  4. This one enhances debug helpers in dwarf2out.c to ease location 
descriptions (DWARF expressions) bugs investigation.


  5. The array_descr_info hook has its own circuitry in dwarf2out.c to 
generate location description: add_descr_info_field. It is a duplicate 
of loc_list_from_tree and less powerful except that it handles 
"self-referencial attributes". This final patch is an attempt to merge 
these two circuitries so that this hook can generate more complex DWARF 
expressions. It also adjusts the Fortran front-end accordingly.


These patches were tested on x86_64-pc-linux-gnu. They trigger no 
regression in the GCC DejaGNU testsuite nor in the GDB one (they fix 
some failures however).

Ok for trunk?

Thank you very much for reading until this point and thank you in 
advance for your review! ;-)

-- 
Pierre-Marie de Rodat


[-- Attachment #2: 0001-Complete-information-generated-through-the-array-des.patch --]
[-- Type: text/x-patch, Size: 6260 bytes --]

From 15f8a12782cfcb084205c751d8c37c7a360bea2f Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Wed, 3 Sep 2014 09:46:17 +0200
Subject: [PATCH 1/5] Complete information generated through the array descr
 language hook

gcc/
	* dwarf2out.h (enum array_descr_ordering): New.
	(array_descr_dimen): Add a bounds_type structure field.
	(struct array_descr_info): Add a field to hold index type information
	and another one to hold ordering information.
	* dwarf2out.c (init_array_descr_info): New.
	(gen_type_die_with_usage): Initialize the array_descr_info structure
	before calling the lang-hook.
	(gen_descr_array_type_die): Use gen_type_die if not processing the main
	type variant.  Replace Fortran-specific code with generic one using
	this new field.  Add a GNAT descriptive type, if any.  Output type
	information for the array bound subrange, if any.

gcc/fortran/
	* trans-types.c (gfc_get_array_descr_info): Describe all Fortran arrays
	with column major ordering.
---
 gcc/dwarf2out.c           | 63 ++++++++++++++++++++++++++++++++++++++++++-----
 gcc/dwarf2out.h           | 13 ++++++++++
 gcc/fortran/trans-types.c |  1 +
 3 files changed, 71 insertions(+), 6 deletions(-)

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 21afc3f..835446e 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -17359,18 +17359,36 @@ static void
 gen_descr_array_type_die (tree type, struct array_descr_info *info,
 			  dw_die_ref context_die)
 {
-  dw_die_ref scope_die = scope_die_for (type, context_die);
+  dw_die_ref scope_die;
   dw_die_ref array_die;
   int dim;
 
+  /* Instead of producing a dedicated DW_TAG_array_type DIE for this type, let
+     the circuitry wrap the main variant with DIEs for qualifiers (for
+     instance: DW_TAG_const_type, ...).  */
+  if (type != TYPE_MAIN_VARIANT (type))
+    {
+      gen_type_die (TYPE_MAIN_VARIANT (type), context_die);
+      return;
+    }
+
+  scope_die = scope_die_for (type, context_die);
   array_die = new_die (DW_TAG_array_type, scope_die, type);
   add_name_attribute (array_die, type_tag (type));
   equate_type_number_to_die (type, array_die);
 
-  /* For Fortran multidimensional arrays use DW_ORD_col_major ordering.  */
-  if (is_fortran ()
-      && info->ndimensions >= 2)
-    add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major);
+  if (info->ndimensions > 1)
+    switch (info->ordering)
+      {
+      case array_descr_ordering_row_major:
+	add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_row_major);
+	break;
+      case array_descr_ordering_column_major:
+	add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major);
+	break;
+      default:
+	break;
+      }
 
   if (info->data_location)
     add_descr_info_field (array_die, DW_AT_data_location, info->data_location,
@@ -17382,11 +17400,17 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
     add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
 			  info->base_decl);
 
+  add_gnat_descriptive_type_attribute (array_die, type, context_die);
+
   for (dim = 0; dim < info->ndimensions; dim++)
     {
       dw_die_ref subrange_die
 	= new_die (DW_TAG_subrange_type, array_die, NULL);
 
+      if (info->dimen[dim].bounds_type)
+	add_type_attribute (subrange_die,
+			    info->dimen[dim].bounds_type, 0,
+			    context_die);
       if (info->dimen[dim].lower_bound)
 	{
 	  /* If it is the default value, omit it.  */
@@ -19884,6 +19908,32 @@ gen_tagged_type_die (tree type,
      when appropriate.  */
 }
 
+/* Initialize an array_descr_info structure with default (null) values and
+   return it.  */
+
+static struct array_descr_info *
+init_array_descr_info (struct array_descr_info *info)
+{
+  int i;
+
+  info->ndimensions = 0;
+  info->ordering = array_descr_ordering_default;
+  info->element_type = NULL_TREE;
+  info->base_decl = NULL_TREE;
+  info->data_location = NULL_TREE;
+  info->allocated = NULL_TREE;
+  info->associated = NULL_TREE;
+
+  for (i = 0; i < 10; ++i)
+    {
+      info->dimen[i].bounds_type = NULL_TREE;
+      info->dimen[i].lower_bound = NULL_TREE;
+      info->dimen[i].upper_bound = NULL_TREE;
+      info->dimen[i].stride = NULL_TREE;
+    }
+  return info;
+}
+
 /* Generate a type description DIE.  */
 
 static void
@@ -19941,7 +19991,8 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
   /* If this is an array type with hidden descriptor, handle it first.  */
   if (!TREE_ASM_WRITTEN (type)
       && lang_hooks.types.get_array_descr_info
-      && lang_hooks.types.get_array_descr_info (type, &info)
+      && lang_hooks.types.get_array_descr_info (type,
+						init_array_descr_info (&info))
       && (dwarf_version >= 3 || !dwarf_strict))
     {
       gen_descr_array_type_die (type, &info, context_die);
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 7843e0a..8b03e78 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -261,16 +261,29 @@ extern void dwarf2out_set_demangle_name_func (const char *(*) (const char *));
 extern void dwarf2out_vms_debug_main_pointer (void);
 #endif
 
+enum array_descr_ordering
+{
+  array_descr_ordering_default,
+  array_descr_ordering_row_major,
+  array_descr_ordering_column_major
+};
+
 struct array_descr_info
 {
   int ndimensions;
+  enum array_descr_ordering ordering;
   tree element_type;
   tree base_decl;
   tree data_location;
   tree allocated;
   tree associated;
+
   struct array_descr_dimen
     {
+      /* GCC uses sizetype for array indices, so lower_bound and upper_bound
+	 will likely be "sizetype" values. However, bounds may have another
+	 type in the original source code.  */
+      tree bounds_type;
       tree lower_bound;
       tree upper_bound;
       tree stride;
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index d455bf4..4c10bd9 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -3033,6 +3033,7 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
 
   memset (info, '\0', sizeof (*info));
   info->ndimensions = rank;
+  info->ordering = array_descr_ordering_column_major;
   info->element_type = etype;
   ptype = build_pointer_type (gfc_array_index_type);
   base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
-- 
2.1.0


[-- Attachment #3: 0002-Enable-the-array-descr-language-hook-for-all-DWARF-v.patch --]
[-- Type: text/x-patch, Size: 2894 bytes --]

From 0d683ca8c1fcf8d780928f1cd629e7a99651c9c0 Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Wed, 3 Sep 2014 09:46:25 +0200
Subject: [PATCH 2/5] Enable the array descr language hook for all DWARF
 versions

	* dwarf2out.c (gen_type_die_with_usage): Enable the array lang-hook
	even when (dwarf_version < 3 && dwarf_strict).
	(gen_descr_array_die): Do not output DW_AT_data_locationn,
	DW_AT_associated, DW_AT_allocated and DW_AT_byte_stride DWARF
	attributes when (dwarf_version < 3 && dwarf_strict).
---
 gcc/dwarf2out.c | 36 +++++++++++++++++++++---------------
 1 file changed, 21 insertions(+), 15 deletions(-)

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 835446e..78a470f 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -17390,15 +17390,19 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 	break;
       }
 
-  if (info->data_location)
-    add_descr_info_field (array_die, DW_AT_data_location, info->data_location,
-			  info->base_decl);
-  if (info->associated)
-    add_descr_info_field (array_die, DW_AT_associated, info->associated,
-			  info->base_decl);
-  if (info->allocated)
-    add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
-			  info->base_decl);
+  if (dwarf_version >= 3 || !dwarf_strict)
+    {
+      if (info->data_location)
+	add_descr_info_field (array_die, DW_AT_data_location,
+			      info->data_location,
+			      info->base_decl);
+      if (info->associated)
+	add_descr_info_field (array_die, DW_AT_associated, info->associated,
+			      info->base_decl);
+      if (info->allocated)
+	add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
+			      info->base_decl);
+    }
 
   add_gnat_descriptive_type_attribute (array_die, type, context_die);
 
@@ -17429,10 +17433,13 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 	add_descr_info_field (subrange_die, DW_AT_upper_bound,
 			      info->dimen[dim].upper_bound,
 			      info->base_decl);
-      if (info->dimen[dim].stride)
-	add_descr_info_field (subrange_die, DW_AT_byte_stride,
-			      info->dimen[dim].stride,
-			      info->base_decl);
+      if (dwarf_version >= 3 || !dwarf_strict)
+	{
+	  if (info->dimen[dim].stride)
+	    add_descr_info_field (subrange_die, DW_AT_byte_stride,
+				  info->dimen[dim].stride,
+				  info->base_decl);
+	}
     }
 
   gen_type_die (info->element_type, context_die);
@@ -19992,8 +19999,7 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
   if (!TREE_ASM_WRITTEN (type)
       && lang_hooks.types.get_array_descr_info
       && lang_hooks.types.get_array_descr_info (type,
-						init_array_descr_info (&info))
-      && (dwarf_version >= 3 || !dwarf_strict))
+						init_array_descr_info (&info)))
     {
       gen_descr_array_type_die (type, &info, context_die);
       TREE_ASM_WRITTEN (type) = 1;
-- 
2.1.0


[-- Attachment #4: 0003-Make-the-Ada-front-end-use-the-array-descr-language-.patch --]
[-- Type: text/x-patch, Size: 3351 bytes --]

From f2d72fee9c3a8ca9f5e95fccf8de6d342cae36a6 Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Wed, 3 Sep 2014 09:46:27 +0200
Subject: [PATCH 3/5] Make the Ada front-end use the array descr language hook

gcc/ada/
	* gcc-interface/misc.c (gnat_get_array_descr_info): New.  Use it
	for the get_array_descr_info lang-hook.  Use it to tune the DWARF
	output for array types.
---
 gcc/ada/gcc-interface/misc.c | 61 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 240ca44..7449ef9 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -43,6 +43,7 @@
 #include "plugin.h"
 #include "real.h"
 #include "function.h"	/* For pass_by_reference.  */
+#include "dwarf2out.h"
 
 #include "ada.h"
 #include "adadecode.h"
@@ -626,6 +627,64 @@ gnat_type_max_size (const_tree gnu_type)
   return max_unitsize;
 }
 
+/* Provide information in INFO for debug output about the TYPE array type.
+   Return whether TYPE is handled.  */
+
+static bool
+gnat_get_array_descr_info (const_tree type, struct array_descr_info *info)
+{
+  bool convention_fortran_p;
+  tree index_type;
+
+  const_tree dimen, last_dimen;
+  int i;
+
+  if (TREE_CODE (type) != ARRAY_TYPE
+      || !TYPE_DOMAIN (type)
+      || !TYPE_INDEX_TYPE (TYPE_DOMAIN (type)))
+    return false;
+
+  /* Count how many dimentions this array has.  */
+  for (i = 0, dimen = type; ; ++i, dimen = TREE_TYPE (dimen))
+    if (i > 0
+	&& (TREE_CODE (dimen) != ARRAY_TYPE
+	    || !TYPE_MULTI_ARRAY_P (dimen)))
+      break;
+  info->ndimensions = i;
+  convention_fortran_p = TYPE_CONVENTION_FORTRAN_P (type);
+
+  /* TODO??? For row major ordering, we probably want to emit nothing and
+     instead specify it as the default in Dw_TAG_compile_unit.  */
+  info->ordering = (convention_fortran_p
+		    ? array_descr_ordering_column_major
+		    : array_descr_ordering_row_major);
+  info->base_decl = NULL_TREE;
+  info->data_location = NULL_TREE;
+  info->allocated = NULL_TREE;
+  info->associated = NULL_TREE;
+
+  for (i = (convention_fortran_p ? info->ndimensions - 1 : 0),
+       dimen = type;
+
+       0 <= i && i < info->ndimensions;
+
+       i += (convention_fortran_p ? -1 : 1),
+       dimen = TREE_TYPE (dimen))
+    {
+      /* We are interested in the stored bounds for the debug info.  */
+      index_type = TYPE_INDEX_TYPE (TYPE_DOMAIN (dimen));
+
+      info->dimen[i].bounds_type = index_type;
+      info->dimen[i].lower_bound = TYPE_MIN_VALUE (index_type);
+      info->dimen[i].upper_bound = TYPE_MAX_VALUE (index_type);
+      last_dimen = dimen;
+    }
+
+  info->element_type = TREE_TYPE (last_dimen);
+
+  return true;
+}
+
 /* GNU_TYPE is a subtype of an integral type.  Set LOWVAL to the low bound
    and HIGHVAL to the high bound, respectively.  */
 
@@ -916,6 +975,8 @@ gnat_init_ts (void)
 #define LANG_HOOKS_TYPE_FOR_SIZE	gnat_type_for_size
 #undef  LANG_HOOKS_TYPES_COMPATIBLE_P
 #define LANG_HOOKS_TYPES_COMPATIBLE_P	gnat_types_compatible_p
+#undef  LANG_HOOKS_GET_ARRAY_DESCR_INFO
+#define LANG_HOOKS_GET_ARRAY_DESCR_INFO	gnat_get_array_descr_info
 #undef  LANG_HOOKS_GET_SUBRANGE_BOUNDS
 #define LANG_HOOKS_GET_SUBRANGE_BOUNDS  gnat_get_subrange_bounds
 #undef  LANG_HOOKS_DESCRIPTIVE_TYPE
-- 
2.1.0


[-- Attachment #5: 0004-Add-a-few-debug-utilities-for-DWARF-expressions.patch --]
[-- Type: text/x-patch, Size: 9829 bytes --]

From 166fcbad8529818e492c57b7b9091799bf3ae72d Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Wed, 3 Sep 2014 09:46:29 +0200
Subject: [PATCH 4/5] Add a few debug utilities for DWARF expressions

	* dwarf2out.c (print_loc_descr): New.
	(print_dw_val): New.
	(print_attribute): New.
	(print_loc_descr): New.
	(print_die): Use print_dw_val.
	(debug_dwarf_loc_descr): New.
	* dwarf2out.h (debug_dwarf_loc_descr): New declaration.
---
 gcc/dwarf2out.c | 277 +++++++++++++++++++++++++++++++++++---------------------
 gcc/dwarf2out.h |   1 +
 2 files changed, 176 insertions(+), 102 deletions(-)

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 78a470f..1638da4 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -5337,6 +5337,172 @@ print_signature (FILE *outfile, char *sig)
     fprintf (outfile, "%02x", sig[i] & 0xff);
 }
 
+static void print_loc_descr (dw_loc_descr_ref, FILE *);
+
+/* Print the value associated to the VAL DWARF value node to OUTFILE.  If
+   RECURSE, output location descriptor operations.  */
+
+static void
+print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
+{
+  switch (val->val_class)
+    {
+    case dw_val_class_addr:
+      fprintf (outfile, "address");
+      break;
+    case dw_val_class_offset:
+      fprintf (outfile, "offset");
+      break;
+    case dw_val_class_loc:
+      fprintf (outfile, "location descriptor");
+      if (val->v.val_loc == NULL)
+	fprintf (outfile, " -> <null>\n");
+      else if (recurse)
+	{
+	  fprintf (outfile, ":\n");
+	  print_indent += 4;
+	  print_loc_descr (val->v.val_loc, outfile);
+	  print_indent -= 4;
+	}
+      else
+	fprintf (outfile, " (%p)\n", (void *) val->v.val_loc);
+      break;
+    case dw_val_class_loc_list:
+      fprintf (outfile, "location list -> label:%s",
+	       val->v.val_loc_list->ll_symbol);
+      break;
+    case dw_val_class_range_list:
+      fprintf (outfile, "range list");
+      break;
+    case dw_val_class_const:
+      fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, val->v.val_int);
+      break;
+    case dw_val_class_unsigned_const:
+      fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, val->v.val_unsigned);
+      break;
+    case dw_val_class_const_double:
+      fprintf (outfile, "constant ("HOST_WIDE_INT_PRINT_DEC","\
+			HOST_WIDE_INT_PRINT_UNSIGNED")",
+	       val->v.val_double.high,
+	       val->v.val_double.low);
+      break;
+    case dw_val_class_wide_int:
+      {
+	int i = val->v.val_wide->get_len ();
+	fprintf (outfile, "constant (");
+	gcc_assert (i > 0);
+	if (val->v.val_wide->elt (i - 1) == 0)
+	  fprintf (outfile, "0x");
+	fprintf (outfile, HOST_WIDE_INT_PRINT_HEX,
+		 val->v.val_wide->elt (--i));
+	while (--i >= 0)
+	  fprintf (outfile, HOST_WIDE_INT_PRINT_PADDED_HEX,
+		   val->v.val_wide->elt (i));
+	fprintf (outfile, ")");
+	break;
+      }
+    case dw_val_class_vec:
+      fprintf (outfile, "floating-point or vector constant");
+      break;
+    case dw_val_class_flag:
+      fprintf (outfile, "%u", val->v.val_flag);
+      break;
+    case dw_val_class_die_ref:
+      if (val->v.val_die_ref.die != NULL)
+	{
+	  dw_die_ref die = val->v.val_die_ref.die;
+
+	  if (die->comdat_type_p)
+	    {
+	      fprintf (outfile, "die -> signature: ");
+	      print_signature (outfile,
+			       die->die_id.die_type_node->signature);
+	    }
+	  else if (die->die_id.die_symbol)
+	    fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
+	  else
+	    fprintf (outfile, "die -> %ld", die->die_offset);
+	  fprintf (outfile, " (%p)", (void *) die);
+	}
+      else
+	fprintf (outfile, "die -> <null>");
+      break;
+    case dw_val_class_vms_delta:
+      fprintf (outfile, "delta: @slotcount(%s-%s)",
+	       val->v.val_vms_delta.lbl2, val->v.val_vms_delta.lbl1);
+      break;
+    case dw_val_class_lbl_id:
+    case dw_val_class_lineptr:
+    case dw_val_class_macptr:
+    case dw_val_class_high_pc:
+      fprintf (outfile, "label: %s", val->v.val_lbl_id);
+      break;
+    case dw_val_class_str:
+      if (val->v.val_str->str != NULL)
+	fprintf (outfile, "\"%s\"", val->v.val_str->str);
+      else
+	fprintf (outfile, "<null>");
+      break;
+    case dw_val_class_file:
+      fprintf (outfile, "\"%s\" (%d)", val->v.val_file->filename,
+	       val->v.val_file->emitted_number);
+      break;
+    case dw_val_class_data8:
+      {
+	int i;
+
+	for (i = 0; i < 8; i++)
+	  fprintf (outfile, "%02x", val->v.val_data8[i]);
+	break;
+      }
+    default:
+      break;
+    }
+}
+
+/* Likewise, for a DIE attribute.  */
+
+static void
+print_attribute (dw_attr_ref a, bool recurse, FILE *outfile)
+{
+  print_dw_val (&a->dw_attr_val, recurse, outfile);
+}
+
+/* Print the list of operands in the LOC location description to OUTFILE.  This
+   routine is a debugging aid only.  */
+
+static void
+print_loc_descr (dw_loc_descr_ref loc, FILE *outfile)
+{
+  dw_loc_descr_ref l = loc;
+
+  if (loc == NULL)
+    {
+      print_spaces (outfile);
+      fprintf (outfile, "<null>\n");
+      return;
+    }
+
+  for (l = loc; l != NULL; l = l->dw_loc_next)
+    {
+      print_spaces (outfile);
+      fprintf (outfile, "(%p) %s",
+	       (void *) l,
+	       dwarf_stack_op_name (l->dw_loc_opc));
+      if (l->dw_loc_oprnd1.val_class != dw_val_class_none)
+	{
+	  fprintf (outfile, " ");
+	  print_dw_val (&l->dw_loc_oprnd1, false, outfile);
+	}
+      if (l->dw_loc_oprnd2.val_class != dw_val_class_none)
+	{
+	  fprintf (outfile, ", ");
+	  print_dw_val (&l->dw_loc_oprnd2, false, outfile);
+	}
+      fprintf (outfile, "\n");
+    }
+}
+
 /* Print the information associated with a given DIE, and its children.
    This routine is a debugging aid only.  */
 
@@ -5369,108 +5535,7 @@ print_die (dw_die_ref die, FILE *outfile)
       print_spaces (outfile);
       fprintf (outfile, "  %s: ", dwarf_attr_name (a->dw_attr));
 
-      switch (AT_class (a))
-	{
-	case dw_val_class_addr:
-	  fprintf (outfile, "address");
-	  break;
-	case dw_val_class_offset:
-	  fprintf (outfile, "offset");
-	  break;
-	case dw_val_class_loc:
-	  fprintf (outfile, "location descriptor");
-	  break;
-	case dw_val_class_loc_list:
-	  fprintf (outfile, "location list -> label:%s",
-		   AT_loc_list (a)->ll_symbol);
-	  break;
-	case dw_val_class_range_list:
-	  fprintf (outfile, "range list");
-	  break;
-	case dw_val_class_const:
-	  fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, AT_int (a));
-	  break;
-	case dw_val_class_unsigned_const:
-	  fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, AT_unsigned (a));
-	  break;
-	case dw_val_class_const_double:
-	  fprintf (outfile, "constant ("HOST_WIDE_INT_PRINT_DEC","\
-			    HOST_WIDE_INT_PRINT_UNSIGNED")",
-		   a->dw_attr_val.v.val_double.high,
-		   a->dw_attr_val.v.val_double.low);
-	  break;
-	case dw_val_class_wide_int:
-	  {
-	    int i = a->dw_attr_val.v.val_wide->get_len ();
-	    fprintf (outfile, "constant (");
-	    gcc_assert (i > 0);
-	    if (a->dw_attr_val.v.val_wide->elt (i - 1) == 0)
-	      fprintf (outfile, "0x");
-	    fprintf (outfile, HOST_WIDE_INT_PRINT_HEX,
-		     a->dw_attr_val.v.val_wide->elt (--i));
-	    while (--i >= 0)
-	      fprintf (outfile, HOST_WIDE_INT_PRINT_PADDED_HEX,
-		       a->dw_attr_val.v.val_wide->elt (i));
-	    fprintf (outfile, ")");
-	    break;
-	  }
-	case dw_val_class_vec:
-	  fprintf (outfile, "floating-point or vector constant");
-	  break;
-	case dw_val_class_flag:
-	  fprintf (outfile, "%u", AT_flag (a));
-	  break;
-	case dw_val_class_die_ref:
-	  if (AT_ref (a) != NULL)
-	    {
-	      if (AT_ref (a)->comdat_type_p)
-	        {
-		  fprintf (outfile, "die -> signature: ");
-		  print_signature (outfile,
-		  		   AT_ref (a)->die_id.die_type_node->signature);
-                }
-	      else if (AT_ref (a)->die_id.die_symbol)
-		fprintf (outfile, "die -> label: %s",
-		         AT_ref (a)->die_id.die_symbol);
-	      else
-		fprintf (outfile, "die -> %ld", AT_ref (a)->die_offset);
-	      fprintf (outfile, " (%p)", (void *) AT_ref (a));
-	    }
-	  else
-	    fprintf (outfile, "die -> <null>");
-	  break;
-	case dw_val_class_vms_delta:
-	  fprintf (outfile, "delta: @slotcount(%s-%s)",
-		   AT_vms_delta2 (a), AT_vms_delta1 (a));
-	  break;
-	case dw_val_class_lbl_id:
-	case dw_val_class_lineptr:
-	case dw_val_class_macptr:
-	case dw_val_class_high_pc:
-	  fprintf (outfile, "label: %s", AT_lbl (a));
-	  break;
-	case dw_val_class_str:
-	  if (AT_string (a) != NULL)
-	    fprintf (outfile, "\"%s\"", AT_string (a));
-	  else
-	    fprintf (outfile, "<null>");
-	  break;
-	case dw_val_class_file:
-	  fprintf (outfile, "\"%s\" (%d)", AT_file (a)->filename,
-		   AT_file (a)->emitted_number);
-	  break;
-	case dw_val_class_data8:
-	  {
-	    int i;
-
-            for (i = 0; i < 8; i++)
-              fprintf (outfile, "%02x", a->dw_attr_val.v.val_data8[i]);
-	    break;
-          }
-	default:
-	  break;
-	}
-
+      print_attribute (a, true, outfile);
       fprintf (outfile, "\n");
     }
 
@@ -5484,6 +5549,14 @@ print_die (dw_die_ref die, FILE *outfile)
     fprintf (outfile, "\n");
 }
 
+/* Print the list of operations in the LOC location description.  */
+
+DEBUG_FUNCTION void
+debug_dwarf_loc_descr (dw_loc_descr_ref loc)
+{
+  print_loc_descr (loc, stderr);
+}
+
 /* Print the information collected for a given DIE.  */
 
 DEBUG_FUNCTION void
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 8b03e78..fbcb70a 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -254,6 +254,7 @@ extern void dwarf2out_emit_cfi (dw_cfi_ref cfi);
 extern void debug_dwarf (void);
 struct die_struct;
 extern void debug_dwarf_die (struct die_struct *);
+extern void debug_dwarf_loc_descr (dw_loc_descr_ref);
 extern void debug (die_struct &ref);
 extern void debug (die_struct *ptr);
 extern void dwarf2out_set_demangle_name_func (const char *(*) (const char *));
-- 
2.1.0


[-- Attachment #6: 0005-dwarf2out.c-do-not-short-circuit-add_bound_info-in-a.patch --]
[-- Type: text/x-patch, Size: 19807 bytes --]

From e029b9300c58a0ffbfa1b7f81381a937a60b27fd Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Wed, 3 Sep 2014 09:46:32 +0200
Subject: [PATCH 5/5] dwarf2out.c: do not short-circuit add_bound_info in array
 lang-hook

gcc/
	* dwarf2out.h (struct array_descr_info): Remove the base_decl field.
	* dwarf2out.c (init_array_descr_info): Update accordingly.
	(enum dw_scalar_form): New.
	(add_scalar_info): New.
	(loc_list_from_tree): Handle PLACEHOLDER_EXPR nodes for
	type-related expressions.
	(add_bound_info): Use add_scalar_info.
	(descr_info_loc): Remove.
	(add_descr_info_field): Remove.
	(gen_descr_array_type_die): Switch add_descr_info_field calls
	into add_scalar_info/add_bound_info ones.

gcc/ada/
	* gcc-interface/misc.c (gnat_get_array_descr_info): Remove base_decl
	initialization.

gcc/fortran/
	* trans-types.c (gfc_get_array_descr_info): Use PLACEHOLDER_EXPR nodes
	instead of VAR_DECL ones in type-related expressions.  Remove base_decl
	initialization.
---
 gcc/ada/gcc-interface/misc.c |   1 -
 gcc/dwarf2out.c              | 434 ++++++++++++++++++++-----------------------
 gcc/dwarf2out.h              |   1 -
 gcc/fortran/trans-types.c    |   5 +-
 4 files changed, 203 insertions(+), 238 deletions(-)

diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 7449ef9..0661d49 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -658,7 +658,6 @@ gnat_get_array_descr_info (const_tree type, struct array_descr_info *info)
   info->ordering = (convention_fortran_p
 		    ? array_descr_ordering_column_major
 		    : array_descr_ordering_row_major);
-  info->base_decl = NULL_TREE;
   info->data_location = NULL_TREE;
   info->allocated = NULL_TREE;
   info->associated = NULL_TREE;
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 1638da4..18f46de 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -2981,6 +2981,15 @@ static bool frame_pointer_fb_offset_valid;
 
 static vec<dw_die_ref> base_types;
 
+/* Flags to represent a set of attribute classes for attributes that represent
+   a scalar value (bounds, pointers, ...).  */
+enum dw_scalar_form
+{
+  dw_scalar_form_constant = 0x01,
+  dw_scalar_form_exprloc = 0x02,
+  dw_scalar_form_reference = 0x04
+};
+
 /* Forward declarations for functions defined in this file.  */
 
 static int is_pseudo_reg (const_rtx);
@@ -3186,6 +3195,7 @@ static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
 static void add_name_attribute (dw_die_ref, const char *);
 static void add_gnat_descriptive_type_attribute (dw_die_ref, tree, dw_die_ref);
 static void add_comp_dir_attribute (dw_die_ref);
+static void add_scalar_info (dw_die_ref, enum dwarf_attribute, tree, int);
 static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
 static void add_subscript_info (dw_die_ref, tree, bool);
 static void add_byte_size_attribute (dw_die_ref, tree);
@@ -14283,11 +14293,19 @@ loc_list_from_tree (tree loc, int want_address)
 
     case PLACEHOLDER_EXPR:
       /* This case involves extracting fields from an object to determine the
-	 position of other fields.  We don't try to encode this here.  The
-	 only user of this is Ada, which encodes the needed information using
-	 the names of types.  */
-      expansion_failed (loc, NULL_RTX, "PLACEHOLDER_EXPR");
-      return 0;
+	 position of other fields. It is supposed to appear only as the first
+	 operand of COMPONENT_REF nodes.  */
+      if (TREE_CODE (TREE_TYPE (loc)) == RECORD_TYPE
+	  && want_address >= 1)
+	{
+	  ret = new_loc_descr (DW_OP_push_object_address, 0, 0);
+	  have_address = 1;
+	  break;
+	}
+      else
+	expansion_failed (loc, NULL_RTX,
+			  "PLACEHOLDER_EXPR for a non-structure");
+      break;
 
     case CALL_EXPR:
       expansion_failed (loc, NULL_RTX, "CALL_EXPR");
@@ -16389,6 +16407,141 @@ add_comp_dir_attribute (dw_die_ref die)
     add_AT_string (die, DW_AT_comp_dir, wd);
 }
 
+/* Given a tree node VALUE describing a scalar attribute ATTR (i.e. a bound, a
+   pointer computation, ...), output a representation for that bound according
+   to the accepted FORMS (see enum dw_scalar_form) and add it to DIE.  */
+
+static void
+add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
+		 int forms)
+{
+  dw_die_ref ctx, decl_die;
+  dw_loc_list_ref list;
+
+  bool pell_conversions = true;
+
+  while (pell_conversions)
+    switch (TREE_CODE (value))
+      {
+      case ERROR_MARK:
+      case SAVE_EXPR:
+	return;
+
+      CASE_CONVERT:
+      case VIEW_CONVERT_EXPR:
+	value = TREE_OPERAND (value, 0);
+	break;
+
+      default:
+	pell_conversions = false;
+	break;
+      }
+
+  /* If possible and permitted, output the attribute as a constant.  */
+  if ((forms & dw_scalar_form_constant) != 0
+      && TREE_CODE (value) == INTEGER_CST)
+    {
+      unsigned int prec = simple_type_size_in_bits (TREE_TYPE (value));
+
+      /* If HOST_WIDE_INT is big enough then represent the bound as
+	 a constant value.  We need to choose a form based on
+	 whether the type is signed or unsigned.  We cannot just
+	 call add_AT_unsigned if the value itself is positive
+	 (add_AT_unsigned might add the unsigned value encoded as
+	 DW_FORM_data[1248]).  Some DWARF consumers will lookup the
+	 bounds type and then sign extend any unsigned values found
+	 for signed types.  This is needed only for
+	 DW_AT_{lower,upper}_bound, since for most other attributes,
+	 consumers will treat DW_FORM_data[1248] as unsigned values,
+	 regardless of the underlying type.  */
+      if (prec <= HOST_BITS_PER_WIDE_INT
+	       || tree_fits_uhwi_p (value))
+	{
+	  if (TYPE_UNSIGNED (TREE_TYPE (value)))
+	    add_AT_unsigned (die, attr, TREE_INT_CST_LOW (value));
+	  else
+	    add_AT_int (die, attr, TREE_INT_CST_LOW (value));
+	}
+      else
+	/* Otherwise represent the bound as an unsigned value with
+	   the precision of its type.  The precision and signedness
+	   of the type will be necessary to re-interpret it
+	   unambiguously.  */
+	add_AT_wide (die, attr, value);
+    }
+
+  /* Otherwise, if it's possible and permitted too, output a reference to
+     another DIE.  */
+  if ((forms & dw_scalar_form_reference) != 0)
+    {
+      tree decl = NULL_TREE;
+
+      /* Some type attributes reference an outer type.  For instance, the upper
+	 bound of an array may reference an embedding record (this happens in
+	 Ada).  */
+      if (TREE_CODE (value) == COMPONENT_REF
+	  && TREE_CODE (TREE_OPERAND (value, 0)) == PLACEHOLDER_EXPR
+	  && TREE_CODE (TREE_OPERAND (value, 1)) == FIELD_DECL)
+	decl = TREE_OPERAND (value, 1);
+
+      else if (TREE_CODE (value) == VAR_DECL
+	       || TREE_CODE (value) == PARM_DECL
+	       || TREE_CODE (value) == RESULT_DECL)
+	decl = value;
+
+      if (decl != NULL_TREE)
+	{
+	  dw_die_ref decl_die = lookup_decl_die (decl);
+
+	  /* ??? Can this happen, or should the variable have been bound
+	     first?  Probably it can, since I imagine that we try to create
+	     the types of parameters in the order in which they exist in
+	     the list, and won't have created a forward reference to a
+	     later parameter.  */
+	  if (decl_die != NULL)
+	    {
+	      add_AT_die_ref (die, attr, decl_die);
+	      return;
+	    }
+	}
+    }
+
+  /* Last chance: try to create a stack operation procedure to evaluate the
+     value.  Do nothing if even that is not possible or permitted.  */
+  if ((forms & dw_scalar_form_exprloc) == 0)
+    return;
+
+  list = loc_list_from_tree (value, 2);
+  if (list == NULL || single_element_loc_list_p (list))
+    {
+      /* If this attribute is not a reference nor constant, it is
+	 a DWARF expression rather than location description.  For that
+	 loc_list_from_tree (value, 0) is needed.  */
+      dw_loc_list_ref list2 = loc_list_from_tree (value, 0);
+      if (list2 && single_element_loc_list_p (list2))
+	{
+	  add_AT_loc (die, attr, list2->expr);
+	  return;
+	}
+    }
+
+  /* If that failed to give a single element location list, fall back to
+     outputting this as a reference... still if permitted.  */
+  if (list == NULL || (forms & dw_scalar_form_reference) == 0)
+    return;
+
+  if (current_function_decl == 0)
+    ctx = comp_unit_die ();
+  else
+    ctx = lookup_decl_die (current_function_decl);
+
+  decl_die = new_die (DW_TAG_variable, ctx, value);
+  add_AT_flag (decl_die, DW_AT_artificial, 1);
+  add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, ctx);
+  add_AT_location_description (decl_die, DW_AT_location, list);
+  add_AT_die_ref (die, attr, decl_die);
+}
+
 /* Return the default for DW_AT_lower_bound, or -1 if there is not any
    default.  */
 
@@ -16430,121 +16583,40 @@ lower_bound_default (void)
    a representation for that bound.  */
 
 static void
-add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree bound)
+add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr,
+		tree bound)
 {
-  switch (TREE_CODE (bound))
-    {
-    case ERROR_MARK:
-      return;
+  int dflt;
 
-    /* All fixed-bounds are represented by INTEGER_CST nodes.  */
-    case INTEGER_CST:
+  while (1)
+    switch (TREE_CODE (bound))
       {
-	unsigned int prec = simple_type_size_in_bits (TREE_TYPE (bound));
-	int dflt;
+      /* Pell all conversions.  */
+      CASE_CONVERT:
+      case VIEW_CONVERT_EXPR:
+	bound = TREE_OPERAND (bound, 0);
+	break;
 
-	/* Use the default if possible.  */
+      /* All fixed-bounds are represented by INTEGER_CST nodes.  Lower bounds
+	 are even omitted when they are the default.  */
+      case INTEGER_CST:
+	/* If the value for this bound is the default one, we can even omit the
+	   attribute.  */
 	if (bound_attr == DW_AT_lower_bound
 	    && tree_fits_shwi_p (bound)
 	    && (dflt = lower_bound_default ()) != -1
 	    && tree_to_shwi (bound) == dflt)
-	  ;
-
-	/* If HOST_WIDE_INT is big enough then represent the bound as
-	   a constant value.  We need to choose a form based on
-	   whether the type is signed or unsigned.  We cannot just
-	   call add_AT_unsigned if the value itself is positive
-	   (add_AT_unsigned might add the unsigned value encoded as
-	   DW_FORM_data[1248]).  Some DWARF consumers will lookup the
-	   bounds type and then sign extend any unsigned values found
-	   for signed types.  This is needed only for
-	   DW_AT_{lower,upper}_bound, since for most other attributes,
-	   consumers will treat DW_FORM_data[1248] as unsigned values,
-	   regardless of the underlying type.  */
-	else if (prec <= HOST_BITS_PER_WIDE_INT
-		 || tree_fits_uhwi_p (bound))
-	  {
-	    if (TYPE_UNSIGNED (TREE_TYPE (bound)))
-	      add_AT_unsigned (subrange_die, bound_attr,
-			       TREE_INT_CST_LOW (bound));
-	    else
-	      add_AT_int (subrange_die, bound_attr, TREE_INT_CST_LOW (bound));
-	  }
-	else
-	  /* Otherwise represent the bound as an unsigned value with
-	     the precision of its type.  The precision and signedness
-	     of the type will be necessary to re-interpret it
-	     unambiguously.  */
-	  add_AT_wide (subrange_die, bound_attr, bound);
-      }
-      break;
-
-    CASE_CONVERT:
-    case VIEW_CONVERT_EXPR:
-      add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0));
-      break;
-
-    case SAVE_EXPR:
-      break;
-
-    case VAR_DECL:
-    case PARM_DECL:
-    case RESULT_DECL:
-      {
-	dw_die_ref decl_die = lookup_decl_die (bound);
-
-	/* ??? Can this happen, or should the variable have been bound
-	   first?  Probably it can, since I imagine that we try to create
-	   the types of parameters in the order in which they exist in
-	   the list, and won't have created a forward reference to a
-	   later parameter.  */
-	if (decl_die != NULL)
-	  {
-	    add_AT_die_ref (subrange_die, bound_attr, decl_die);
-	    break;
-	  }
-      }
-      /* FALLTHRU */
-
-    default:
-      {
-	/* Otherwise try to create a stack operation procedure to
-	   evaluate the value of the array bound.  */
-
-	dw_die_ref ctx, decl_die;
-	dw_loc_list_ref list;
-
-	list = loc_list_from_tree (bound, 2);
-	if (list == NULL || single_element_loc_list_p (list))
-	  {
-	    /* If DW_AT_*bound is not a reference nor constant, it is
-	       a DWARF expression rather than location description.
-	       For that loc_list_from_tree (bound, 0) is needed.
-	       If that fails to give a single element list,
-	       fall back to outputting this as a reference anyway.  */
-	    dw_loc_list_ref list2 = loc_list_from_tree (bound, 0);
-	    if (list2 && single_element_loc_list_p (list2))
-	      {
-		add_AT_loc (subrange_die, bound_attr, list2->expr);
-		break;
-	      }
-	  }
-	if (list == NULL)
-	  break;
+	  return;
 
-	if (current_function_decl == 0)
-	  ctx = comp_unit_die ();
-	else
-	  ctx = lookup_decl_die (current_function_decl);
+	/* FALLTHRU */
 
-	decl_die = new_die (DW_TAG_variable, ctx, bound);
-	add_AT_flag (decl_die, DW_AT_artificial, 1);
-	add_type_attribute (decl_die, TREE_TYPE (bound), TYPE_QUAL_CONST, ctx);
-	add_AT_location_description (decl_die, DW_AT_location, list);
-	add_AT_die_ref (subrange_die, bound_attr, decl_die);
-	break;
+      default:
+	add_scalar_info (subrange_die, bound_attr, bound,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference);
+	return;
       }
-    }
 }
 
 /* Add subscript info to TYPE_DIE, describing an array TYPE, collapsing
@@ -17332,99 +17404,6 @@ gen_array_type_die (tree type, dw_die_ref context_die)
     add_pubtype (type, array_die);
 }
 
-static dw_loc_descr_ref
-descr_info_loc (tree val, tree base_decl)
-{
-  HOST_WIDE_INT size;
-  dw_loc_descr_ref loc, loc2;
-  enum dwarf_location_atom op;
-
-  if (val == base_decl)
-    return new_loc_descr (DW_OP_push_object_address, 0, 0);
-
-  switch (TREE_CODE (val))
-    {
-    CASE_CONVERT:
-      return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-    case VAR_DECL:
-      return loc_descriptor_from_tree (val, 0);
-    case INTEGER_CST:
-      if (tree_fits_shwi_p (val))
-	return int_loc_descriptor (tree_to_shwi (val));
-      break;
-    case INDIRECT_REF:
-      size = int_size_in_bytes (TREE_TYPE (val));
-      if (size < 0)
-	break;
-      loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-      if (!loc)
-	break;
-      if (size == DWARF2_ADDR_SIZE)
-	add_loc_descr (&loc, new_loc_descr (DW_OP_deref, 0, 0));
-      else
-	add_loc_descr (&loc, new_loc_descr (DW_OP_deref_size, size, 0));
-      return loc;
-    case POINTER_PLUS_EXPR:
-    case PLUS_EXPR:
-      if (tree_fits_uhwi_p (TREE_OPERAND (val, 1))
-	  && tree_to_uhwi (TREE_OPERAND (val, 1)) < 16384)
-	{
-	  loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-	  if (!loc)
-	    break;
-	  loc_descr_plus_const (&loc, tree_to_shwi (TREE_OPERAND (val, 1)));
-	}
-      else
-	{
-	  op = DW_OP_plus;
-	do_binop:
-	  loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-	  if (!loc)
-	    break;
-	  loc2 = descr_info_loc (TREE_OPERAND (val, 1), base_decl);
-	  if (!loc2)
-	    break;
-	  add_loc_descr (&loc, loc2);
-	  add_loc_descr (&loc2, new_loc_descr (op, 0, 0));
-	}
-      return loc;
-    case MINUS_EXPR:
-      op = DW_OP_minus;
-      goto do_binop;
-    case MULT_EXPR:
-      op = DW_OP_mul;
-      goto do_binop;
-    case EQ_EXPR:
-      op = DW_OP_eq;
-      goto do_binop;
-    case NE_EXPR:
-      op = DW_OP_ne;
-      goto do_binop;
-    default:
-      break;
-    }
-  return NULL;
-}
-
-static void
-add_descr_info_field (dw_die_ref die, enum dwarf_attribute attr,
-		      tree val, tree base_decl)
-{
-  dw_loc_descr_ref loc;
-
-  if (tree_fits_shwi_p (val))
-    {
-      add_AT_unsigned (die, attr, tree_to_shwi (val));
-      return;
-    }
-
-  loc = descr_info_loc (val, base_decl);
-  if (!loc)
-    return;
-
-  add_AT_loc (die, attr, loc);
-}
-
 /* This routine generates DIE for array with hidden descriptor, details
    are filled into *info by a langhook.  */
 
@@ -17466,15 +17445,18 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
   if (dwarf_version >= 3 || !dwarf_strict)
     {
       if (info->data_location)
-	add_descr_info_field (array_die, DW_AT_data_location,
-			      info->data_location,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_data_location, info->data_location,
+			 dw_scalar_form_exprloc);
       if (info->associated)
-	add_descr_info_field (array_die, DW_AT_associated, info->associated,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_associated, info->associated,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference);
       if (info->allocated)
-	add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_allocated, info->allocated,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference);
     }
 
   add_gnat_descriptive_type_attribute (array_die, type, context_die);
@@ -17489,30 +17471,17 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 			    info->dimen[dim].bounds_type, 0,
 			    context_die);
       if (info->dimen[dim].lower_bound)
-	{
-	  /* If it is the default value, omit it.  */
-	  int dflt;
-
-	  if (tree_fits_shwi_p (info->dimen[dim].lower_bound)
-	      && (dflt = lower_bound_default ()) != -1
-	      && tree_to_shwi (info->dimen[dim].lower_bound) == dflt)
-	    ;
-	  else
-	    add_descr_info_field (subrange_die, DW_AT_lower_bound,
-				  info->dimen[dim].lower_bound,
-				  info->base_decl);
-	}
+	add_bound_info (subrange_die, DW_AT_lower_bound,
+			info->dimen[dim].lower_bound);
       if (info->dimen[dim].upper_bound)
-	add_descr_info_field (subrange_die, DW_AT_upper_bound,
-			      info->dimen[dim].upper_bound,
-			      info->base_decl);
-      if (dwarf_version >= 3 || !dwarf_strict)
-	{
-	  if (info->dimen[dim].stride)
-	    add_descr_info_field (subrange_die, DW_AT_byte_stride,
-				  info->dimen[dim].stride,
-				  info->base_decl);
-	}
+	add_bound_info (subrange_die, DW_AT_upper_bound,
+			info->dimen[dim].upper_bound);
+      if ((dwarf_version >= 3 || !dwarf_strict) && info->dimen[dim].stride)
+	add_scalar_info (subrange_die, DW_AT_byte_stride,
+			 info->dimen[dim].stride,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference);
     }
 
   gen_type_die (info->element_type, context_die);
@@ -19999,7 +19968,6 @@ init_array_descr_info (struct array_descr_info *info)
   info->ndimensions = 0;
   info->ordering = array_descr_ordering_default;
   info->element_type = NULL_TREE;
-  info->base_decl = NULL_TREE;
   info->data_location = NULL_TREE;
   info->allocated = NULL_TREE;
   info->associated = NULL_TREE;
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index fbcb70a..42e89ae 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -274,7 +274,6 @@ struct array_descr_info
   int ndimensions;
   enum array_descr_ordering ordering;
   tree element_type;
-  tree base_decl;
   tree data_location;
   tree allocated;
   tree associated;
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 4c10bd9..d73beb9 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -3039,11 +3039,10 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
   base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
   if (!base_decl)
     {
-      base_decl = build_decl (input_location, VAR_DECL, NULL_TREE,
-			      indirect ? build_pointer_type (ptype) : ptype);
+      base_decl = build0 (PLACEHOLDER_EXPR,
+			  indirect ? build_pointer_type (ptype) : ptype);
       GFC_TYPE_ARRAY_BASE_DECL (type, indirect) = base_decl;
     }
-  info->base_decl = base_decl;
   if (indirect)
     base_decl = build1 (INDIRECT_REF, ptype, base_decl);
 
-- 
2.1.0


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PING] Enhance array types debug info. for Ada
  2014-09-03  8:36 [PATCH] Enhance array types debug info. for Ada Pierre-Marie de Rodat
@ 2014-09-17 14:38 ` Pierre-Marie de Rodat
  2014-10-03  8:59   ` [PING 2] " Pierre-Marie de Rodat
  2014-10-03 16:42   ` [PING] " Jason Merrill
  2014-10-03  9:19 ` [PATCH] " Jakub Jelinek
  1 sibling, 2 replies; 20+ messages in thread
From: Pierre-Marie de Rodat @ 2014-09-17 14:38 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jakub Jelinek, Jason Merill

Ping for https://gcc.gnu.org/ml/gcc-patches/2014-09/msg00206.html

Adding a few maintainers in copy... Thanks in advance!

-- 
Pierre-Marie de Rodat

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PING 2] Enhance array types debug info. for Ada
  2014-09-17 14:38 ` [PING] " Pierre-Marie de Rodat
@ 2014-10-03  8:59   ` Pierre-Marie de Rodat
  2014-10-03 16:42   ` [PING] " Jason Merrill
  1 sibling, 0 replies; 20+ messages in thread
From: Pierre-Marie de Rodat @ 2014-10-03  8:59 UTC (permalink / raw)
  To: GCC Patches; +Cc: Jakub Jelinek, Jason Merill

On 09/17/2014 04:38 PM, Pierre-Marie de Rodat wrote:
> Ping for https://gcc.gnu.org/ml/gcc-patches/2014-09/msg00206.html
>
> Adding a few maintainers in copy... Thanks in advance!

Should I enhance something in this patch set in order to make the review 
easier? Thanks!

-- 
Pierre-Marie de Rodat

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] Enhance array types debug info. for Ada
  2014-09-03  8:36 [PATCH] Enhance array types debug info. for Ada Pierre-Marie de Rodat
  2014-09-17 14:38 ` [PING] " Pierre-Marie de Rodat
@ 2014-10-03  9:19 ` Jakub Jelinek
  2014-10-03  9:20   ` Jakub Jelinek
  2014-10-07  8:08   ` Pierre-Marie de Rodat
  1 sibling, 2 replies; 20+ messages in thread
From: Jakub Jelinek @ 2014-10-03  9:19 UTC (permalink / raw)
  To: Pierre-Marie de Rodat; +Cc: GCC Patches

On Wed, Sep 03, 2014 at 10:36:21AM +0200, Pierre-Marie de Rodat wrote:
> --- a/gcc/dwarf2out.c
> +++ b/gcc/dwarf2out.c
> @@ -17359,18 +17359,36 @@ static void
>  gen_descr_array_type_die (tree type, struct array_descr_info *info,
>  			  dw_die_ref context_die)
>  {
> -  dw_die_ref scope_die = scope_die_for (type, context_die);
> +  dw_die_ref scope_die;
>    dw_die_ref array_die;
>    int dim;
>  
> +  /* Instead of producing a dedicated DW_TAG_array_type DIE for this type, let
> +     the circuitry wrap the main variant with DIEs for qualifiers (for
> +     instance: DW_TAG_const_type, ...).  */
> +  if (type != TYPE_MAIN_VARIANT (type))
> +    {
> +      gen_type_die (TYPE_MAIN_VARIANT (type), context_die);
> +      return;
> +    }

I don't like this, can you explain why?  I'd say that if you only want
to see TYPE_MAIN_VARIANT here, it should be responsibility of the callers
to ensure that.

> @@ -19941,7 +19991,8 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
>    /* If this is an array type with hidden descriptor, handle it first.  */
>    if (!TREE_ASM_WRITTEN (type)
>        && lang_hooks.types.get_array_descr_info
> -      && lang_hooks.types.get_array_descr_info (type, &info)
> +      && lang_hooks.types.get_array_descr_info (type,
> +						init_array_descr_info (&info))

Just memset it to 0 instead?
> +  enum array_descr_ordering ordering;
>    tree element_type;
>    tree base_decl;
>    tree data_location;
>    tree allocated;
>    tree associated;
> +

Why the extra vertical space?
>    struct array_descr_dimen
>      {

> >From 0d683ca8c1fcf8d780928f1cd629e7a99651c9c0 Mon Sep 17 00:00:00 2001
> From: Pierre-Marie de Rodat <derodat@adacore.com>
> Date: Wed, 3 Sep 2014 09:46:25 +0200
> Subject: [PATCH 2/5] Enable the array descr language hook for all DWARF
>  versions
> 
> 	* dwarf2out.c (gen_type_die_with_usage): Enable the array lang-hook
> 	even when (dwarf_version < 3 && dwarf_strict).
> 	(gen_descr_array_die): Do not output DW_AT_data_locationn,
> 	DW_AT_associated, DW_AT_allocated and DW_AT_byte_stride DWARF
> 	attributes when (dwarf_version < 3 && dwarf_strict).

This patch sounds very wrong.  DW_OP_push_object_address is not in DWARF2
either, and that is the basis of all the fields, so there is really nothing
you can really output correctly for DWARF2.  It isn't the default on sane
targets, where GCC defaults to DWARF4 these days, so why bother?
>  #include "real.h"
>  #include "function.h"	/* For pass_by_reference.  */
> +#include "dwarf2out.h"
>  
>  #include "ada.h"
>  #include "adadecode.h"
> @@ -626,6 +627,64 @@ gnat_type_max_size (const_tree gnu_type)
>    return max_unitsize;
>  }
>  
> +/* Provide information in INFO for debug output about the TYPE array type.
> +   Return whether TYPE is handled.  */
> +
> +static bool
> +gnat_get_array_descr_info (const_tree type, struct array_descr_info *info)
> +{
> +  bool convention_fortran_p;
> +  tree index_type;
> +
> +  const_tree dimen, last_dimen;
> +  int i;
> +
> +  if (TREE_CODE (type) != ARRAY_TYPE
> +      || !TYPE_DOMAIN (type)
> +      || !TYPE_INDEX_TYPE (TYPE_DOMAIN (type)))
> +    return false;
> +
> +  /* Count how many dimentions this array has.  */
> +  for (i = 0, dimen = type; ; ++i, dimen = TREE_TYPE (dimen))
> +    if (i > 0
> +	&& (TREE_CODE (dimen) != ARRAY_TYPE
> +	    || !TYPE_MULTI_ARRAY_P (dimen)))
> +      break;
> +  info->ndimensions = i;
> +  convention_fortran_p = TYPE_CONVENTION_FORTRAN_P (type);
> +
> +  /* TODO??? For row major ordering, we probably want to emit nothing and
> +     instead specify it as the default in Dw_TAG_compile_unit.  */
> +  info->ordering = (convention_fortran_p
> +		    ? array_descr_ordering_column_major
> +		    : array_descr_ordering_row_major);
> +  info->base_decl = NULL_TREE;
> +  info->data_location = NULL_TREE;
> +  info->allocated = NULL_TREE;
> +  info->associated = NULL_TREE;
> +
> +  for (i = (convention_fortran_p ? info->ndimensions - 1 : 0),
> +       dimen = type;
> +
> +       0 <= i && i < info->ndimensions;
> +
> +       i += (convention_fortran_p ? -1 : 1),
> +       dimen = TREE_TYPE (dimen))
> +    {
> +      /* We are interested in the stored bounds for the debug info.  */
> +      index_type = TYPE_INDEX_TYPE (TYPE_DOMAIN (dimen));
> +
> +      info->dimen[i].bounds_type = index_type;
> +      info->dimen[i].lower_bound = TYPE_MIN_VALUE (index_type);
> +      info->dimen[i].upper_bound = TYPE_MAX_VALUE (index_type);
> +      last_dimen = dimen;
> +    }
> +
> +  info->element_type = TREE_TYPE (last_dimen);
> +
> +  return true;
> +}
> +
>  /* GNU_TYPE is a subtype of an integral type.  Set LOWVAL to the low bound
>     and HIGHVAL to the high bound, respectively.  */
>  
> @@ -916,6 +975,8 @@ gnat_init_ts (void)
>  #define LANG_HOOKS_TYPE_FOR_SIZE	gnat_type_for_size
>  #undef  LANG_HOOKS_TYPES_COMPATIBLE_P
>  #define LANG_HOOKS_TYPES_COMPATIBLE_P	gnat_types_compatible_p
> +#undef  LANG_HOOKS_GET_ARRAY_DESCR_INFO
> +#define LANG_HOOKS_GET_ARRAY_DESCR_INFO	gnat_get_array_descr_info
>  #undef  LANG_HOOKS_GET_SUBRANGE_BOUNDS
>  #define LANG_HOOKS_GET_SUBRANGE_BOUNDS  gnat_get_subrange_bounds
>  #undef  LANG_HOOKS_DESCRIPTIVE_TYPE
> -- 
> 2.1.0
> 

> >From 166fcbad8529818e492c57b7b9091799bf3ae72d Mon Sep 17 00:00:00 2001
> From: Pierre-Marie de Rodat <derodat@adacore.com>
> Date: Wed, 3 Sep 2014 09:46:29 +0200
> Subject: [PATCH 4/5] Add a few debug utilities for DWARF expressions
> 
> 	* dwarf2out.c (print_loc_descr): New.
> 	(print_dw_val): New.
> 	(print_attribute): New.
> 	(print_loc_descr): New.
> 	(print_die): Use print_dw_val.
> 	(debug_dwarf_loc_descr): New.
> 	* dwarf2out.h (debug_dwarf_loc_descr): New declaration.
> ---
>  gcc/dwarf2out.c | 277 +++++++++++++++++++++++++++++++++++---------------------
>  gcc/dwarf2out.h |   1 +
>  2 files changed, 176 insertions(+), 102 deletions(-)
> 
> diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
> index 78a470f..1638da4 100644
> --- a/gcc/dwarf2out.c
> +++ b/gcc/dwarf2out.c
> @@ -5337,6 +5337,172 @@ print_signature (FILE *outfile, char *sig)
>      fprintf (outfile, "%02x", sig[i] & 0xff);
>  }
>  
> +static void print_loc_descr (dw_loc_descr_ref, FILE *);
> +
> +/* Print the value associated to the VAL DWARF value node to OUTFILE.  If
> +   RECURSE, output location descriptor operations.  */
> +
> +static void
> +print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
> +{
> +  switch (val->val_class)
> +    {
> +    case dw_val_class_addr:
> +      fprintf (outfile, "address");
> +      break;
> +    case dw_val_class_offset:
> +      fprintf (outfile, "offset");
> +      break;
> +    case dw_val_class_loc:
> +      fprintf (outfile, "location descriptor");
> +      if (val->v.val_loc == NULL)
> +	fprintf (outfile, " -> <null>\n");
> +      else if (recurse)
> +	{
> +	  fprintf (outfile, ":\n");
> +	  print_indent += 4;
> +	  print_loc_descr (val->v.val_loc, outfile);
> +	  print_indent -= 4;
> +	}
> +      else
> +	fprintf (outfile, " (%p)\n", (void *) val->v.val_loc);
> +      break;
> +    case dw_val_class_loc_list:
> +      fprintf (outfile, "location list -> label:%s",
> +	       val->v.val_loc_list->ll_symbol);
> +      break;
> +    case dw_val_class_range_list:
> +      fprintf (outfile, "range list");
> +      break;
> +    case dw_val_class_const:
> +      fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, val->v.val_int);
> +      break;
> +    case dw_val_class_unsigned_const:
> +      fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, val->v.val_unsigned);
> +      break;
> +    case dw_val_class_const_double:
> +      fprintf (outfile, "constant ("HOST_WIDE_INT_PRINT_DEC","\
> +			HOST_WIDE_INT_PRINT_UNSIGNED")",
> +	       val->v.val_double.high,
> +	       val->v.val_double.low);
> +      break;
> +    case dw_val_class_wide_int:
> +      {
> +	int i = val->v.val_wide->get_len ();
> +	fprintf (outfile, "constant (");
> +	gcc_assert (i > 0);
> +	if (val->v.val_wide->elt (i - 1) == 0)
> +	  fprintf (outfile, "0x");
> +	fprintf (outfile, HOST_WIDE_INT_PRINT_HEX,
> +		 val->v.val_wide->elt (--i));
> +	while (--i >= 0)
> +	  fprintf (outfile, HOST_WIDE_INT_PRINT_PADDED_HEX,
> +		   val->v.val_wide->elt (i));
> +	fprintf (outfile, ")");
> +	break;
> +      }
> +    case dw_val_class_vec:
> +      fprintf (outfile, "floating-point or vector constant");
> +      break;
> +    case dw_val_class_flag:
> +      fprintf (outfile, "%u", val->v.val_flag);
> +      break;
> +    case dw_val_class_die_ref:
> +      if (val->v.val_die_ref.die != NULL)
> +	{
> +	  dw_die_ref die = val->v.val_die_ref.die;
> +
> +	  if (die->comdat_type_p)
> +	    {
> +	      fprintf (outfile, "die -> signature: ");
> +	      print_signature (outfile,
> +			       die->die_id.die_type_node->signature);
> +	    }
> +	  else if (die->die_id.die_symbol)
> +	    fprintf (outfile, "die -> label: %s", die->die_id.die_symbol);
> +	  else
> +	    fprintf (outfile, "die -> %ld", die->die_offset);
> +	  fprintf (outfile, " (%p)", (void *) die);
> +	}
> +      else
> +	fprintf (outfile, "die -> <null>");
> +      break;
> +    case dw_val_class_vms_delta:
> +      fprintf (outfile, "delta: @slotcount(%s-%s)",
> +	       val->v.val_vms_delta.lbl2, val->v.val_vms_delta.lbl1);
> +      break;
> +    case dw_val_class_lbl_id:
> +    case dw_val_class_lineptr:
> +    case dw_val_class_macptr:
> +    case dw_val_class_high_pc:
> +      fprintf (outfile, "label: %s", val->v.val_lbl_id);
> +      break;
> +    case dw_val_class_str:
> +      if (val->v.val_str->str != NULL)
> +	fprintf (outfile, "\"%s\"", val->v.val_str->str);
> +      else
> +	fprintf (outfile, "<null>");
> +      break;
> +    case dw_val_class_file:
> +      fprintf (outfile, "\"%s\" (%d)", val->v.val_file->filename,
> +	       val->v.val_file->emitted_number);
> +      break;
> +    case dw_val_class_data8:
> +      {
> +	int i;
> +
> +	for (i = 0; i < 8; i++)
> +	  fprintf (outfile, "%02x", val->v.val_data8[i]);
> +	break;
> +      }
> +    default:
> +      break;
> +    }
> +}
> +
> +/* Likewise, for a DIE attribute.  */
> +
> +static void
> +print_attribute (dw_attr_ref a, bool recurse, FILE *outfile)
> +{
> +  print_dw_val (&a->dw_attr_val, recurse, outfile);
> +}
> +
> +/* Print the list of operands in the LOC location description to OUTFILE.  This
> +   routine is a debugging aid only.  */
> +
> +static void
> +print_loc_descr (dw_loc_descr_ref loc, FILE *outfile)
> +{
> +  dw_loc_descr_ref l = loc;
> +
> +  if (loc == NULL)
> +    {
> +      print_spaces (outfile);
> +      fprintf (outfile, "<null>\n");
> +      return;
> +    }
> +
> +  for (l = loc; l != NULL; l = l->dw_loc_next)
> +    {
> +      print_spaces (outfile);
> +      fprintf (outfile, "(%p) %s",
> +	       (void *) l,
> +	       dwarf_stack_op_name (l->dw_loc_opc));
> +      if (l->dw_loc_oprnd1.val_class != dw_val_class_none)
> +	{
> +	  fprintf (outfile, " ");
> +	  print_dw_val (&l->dw_loc_oprnd1, false, outfile);
> +	}
> +      if (l->dw_loc_oprnd2.val_class != dw_val_class_none)
> +	{
> +	  fprintf (outfile, ", ");
> +	  print_dw_val (&l->dw_loc_oprnd2, false, outfile);
> +	}
> +      fprintf (outfile, "\n");
> +    }
> +}
> +
>  /* Print the information associated with a given DIE, and its children.
>     This routine is a debugging aid only.  */
>  
> @@ -5369,108 +5535,7 @@ print_die (dw_die_ref die, FILE *outfile)
>        print_spaces (outfile);
>        fprintf (outfile, "  %s: ", dwarf_attr_name (a->dw_attr));
>  
> -      switch (AT_class (a))
> -	{
> -	case dw_val_class_addr:
> -	  fprintf (outfile, "address");
> -	  break;
> -	case dw_val_class_offset:
> -	  fprintf (outfile, "offset");
> -	  break;
> -	case dw_val_class_loc:
> -	  fprintf (outfile, "location descriptor");
> -	  break;
> -	case dw_val_class_loc_list:
> -	  fprintf (outfile, "location list -> label:%s",
> -		   AT_loc_list (a)->ll_symbol);
> -	  break;
> -	case dw_val_class_range_list:
> -	  fprintf (outfile, "range list");
> -	  break;
> -	case dw_val_class_const:
> -	  fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, AT_int (a));
> -	  break;
> -	case dw_val_class_unsigned_const:
> -	  fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, AT_unsigned (a));
> -	  break;
> -	case dw_val_class_const_double:
> -	  fprintf (outfile, "constant ("HOST_WIDE_INT_PRINT_DEC","\
> -			    HOST_WIDE_INT_PRINT_UNSIGNED")",
> -		   a->dw_attr_val.v.val_double.high,
> -		   a->dw_attr_val.v.val_double.low);
> -	  break;
> -	case dw_val_class_wide_int:
> -	  {
> -	    int i = a->dw_attr_val.v.val_wide->get_len ();
> -	    fprintf (outfile, "constant (");
> -	    gcc_assert (i > 0);
> -	    if (a->dw_attr_val.v.val_wide->elt (i - 1) == 0)
> -	      fprintf (outfile, "0x");
> -	    fprintf (outfile, HOST_WIDE_INT_PRINT_HEX,
> -		     a->dw_attr_val.v.val_wide->elt (--i));
> -	    while (--i >= 0)
> -	      fprintf (outfile, HOST_WIDE_INT_PRINT_PADDED_HEX,
> -		       a->dw_attr_val.v.val_wide->elt (i));
> -	    fprintf (outfile, ")");
> -	    break;
> -	  }
> -	case dw_val_class_vec:
> -	  fprintf (outfile, "floating-point or vector constant");
> -	  break;
> -	case dw_val_class_flag:
> -	  fprintf (outfile, "%u", AT_flag (a));
> -	  break;
> -	case dw_val_class_die_ref:
> -	  if (AT_ref (a) != NULL)
> -	    {
> -	      if (AT_ref (a)->comdat_type_p)
> -	        {
> -		  fprintf (outfile, "die -> signature: ");
> -		  print_signature (outfile,
> -		  		   AT_ref (a)->die_id.die_type_node->signature);
> -                }
> -	      else if (AT_ref (a)->die_id.die_symbol)
> -		fprintf (outfile, "die -> label: %s",
> -		         AT_ref (a)->die_id.die_symbol);
> -	      else
> -		fprintf (outfile, "die -> %ld", AT_ref (a)->die_offset);
> -	      fprintf (outfile, " (%p)", (void *) AT_ref (a));
> -	    }
> -	  else
> -	    fprintf (outfile, "die -> <null>");
> -	  break;
> -	case dw_val_class_vms_delta:
> -	  fprintf (outfile, "delta: @slotcount(%s-%s)",
> -		   AT_vms_delta2 (a), AT_vms_delta1 (a));
> -	  break;
> -	case dw_val_class_lbl_id:
> -	case dw_val_class_lineptr:
> -	case dw_val_class_macptr:
> -	case dw_val_class_high_pc:
> -	  fprintf (outfile, "label: %s", AT_lbl (a));
> -	  break;
> -	case dw_val_class_str:
> -	  if (AT_string (a) != NULL)
> -	    fprintf (outfile, "\"%s\"", AT_string (a));
> -	  else
> -	    fprintf (outfile, "<null>");
> -	  break;
> -	case dw_val_class_file:
> -	  fprintf (outfile, "\"%s\" (%d)", AT_file (a)->filename,
> -		   AT_file (a)->emitted_number);
> -	  break;
> -	case dw_val_class_data8:
> -	  {
> -	    int i;
> -
> -            for (i = 0; i < 8; i++)
> -              fprintf (outfile, "%02x", a->dw_attr_val.v.val_data8[i]);
> -	    break;
> -          }
> -	default:
> -	  break;
> -	}
> -
> +      print_attribute (a, true, outfile);
>        fprintf (outfile, "\n");
>      }
>  
> @@ -5484,6 +5549,14 @@ print_die (dw_die_ref die, FILE *outfile)
>      fprintf (outfile, "\n");
>  }
>  
> +/* Print the list of operations in the LOC location description.  */
> +
> +DEBUG_FUNCTION void
> +debug_dwarf_loc_descr (dw_loc_descr_ref loc)
> +{
> +  print_loc_descr (loc, stderr);
> +}
> +
>  /* Print the information collected for a given DIE.  */
>  
>  DEBUG_FUNCTION void
> diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
> index 8b03e78..fbcb70a 100644
> --- a/gcc/dwarf2out.h
> +++ b/gcc/dwarf2out.h
> @@ -254,6 +254,7 @@ extern void dwarf2out_emit_cfi (dw_cfi_ref cfi);
>  extern void debug_dwarf (void);
>  struct die_struct;
>  extern void debug_dwarf_die (struct die_struct *);
> +extern void debug_dwarf_loc_descr (dw_loc_descr_ref);
>  extern void debug (die_struct &ref);
>  extern void debug (die_struct *ptr);
>  extern void dwarf2out_set_demangle_name_func (const char *(*) (const char *));
> -- 
> 2.1.0
> 

> >From e029b9300c58a0ffbfa1b7f81381a937a60b27fd Mon Sep 17 00:00:00 2001
> From: Pierre-Marie de Rodat <derodat@adacore.com>
> Date: Wed, 3 Sep 2014 09:46:32 +0200
> Subject: [PATCH 5/5] dwarf2out.c: do not short-circuit add_bound_info in array
>  lang-hook
> 
> gcc/
> 	* dwarf2out.h (struct array_descr_info): Remove the base_decl field.
> 	* dwarf2out.c (init_array_descr_info): Update accordingly.
> 	(enum dw_scalar_form): New.
> 	(add_scalar_info): New.
> 	(loc_list_from_tree): Handle PLACEHOLDER_EXPR nodes for
> 	type-related expressions.
> 	(add_bound_info): Use add_scalar_info.
> 	(descr_info_loc): Remove.
> 	(add_descr_info_field): Remove.
> 	(gen_descr_array_type_die): Switch add_descr_info_field calls
> 	into add_scalar_info/add_bound_info ones.
> 
> gcc/ada/
> 	* gcc-interface/misc.c (gnat_get_array_descr_info): Remove base_decl
> 	initialization.
> 
> gcc/fortran/
> 	* trans-types.c (gfc_get_array_descr_info): Use PLACEHOLDER_EXPR nodes
> 	instead of VAR_DECL ones in type-related expressions.  Remove base_decl
> 	initialization.

Ugh, I must say I don't like PLACEHOLDER_EXPRs at all.

	Jakub

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] Enhance array types debug info. for Ada
  2014-10-03  9:19 ` [PATCH] " Jakub Jelinek
@ 2014-10-03  9:20   ` Jakub Jelinek
  2014-10-07  8:08   ` Pierre-Marie de Rodat
  1 sibling, 0 replies; 20+ messages in thread
From: Jakub Jelinek @ 2014-10-03  9:20 UTC (permalink / raw)
  To: Pierre-Marie de Rodat; +Cc: GCC Patches

On Fri, Oct 03, 2014 at 11:18:48AM +0200, Jakub Jelinek wrote:
> > gcc/fortran/
> > 	* trans-types.c (gfc_get_array_descr_info): Use PLACEHOLDER_EXPR nodes
> > 	instead of VAR_DECL ones in type-related expressions.  Remove base_decl
> > 	initialization.
> 
> Ugh, I must say I don't like PLACEHOLDER_EXPRs at all.

What kind of more complex expressions do you need and why?

	Jakub

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PING] Enhance array types debug info. for Ada
  2014-09-17 14:38 ` [PING] " Pierre-Marie de Rodat
  2014-10-03  8:59   ` [PING 2] " Pierre-Marie de Rodat
@ 2014-10-03 16:42   ` Jason Merrill
  2014-10-07  8:08     ` Pierre-Marie de Rodat
  1 sibling, 1 reply; 20+ messages in thread
From: Jason Merrill @ 2014-10-03 16:42 UTC (permalink / raw)
  To: Pierre-Marie de Rodat, GCC Patches; +Cc: Jakub Jelinek

On 09/17/2014 10:38 AM, Pierre-Marie de Rodat wrote:

Patches 1-4 are OK.

> +  bool pell_conversions = true;

I don't understand "pell".  Do you mean "strip"?

Jason

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PING] Enhance array types debug info. for Ada
  2014-10-03 16:42   ` [PING] " Jason Merrill
@ 2014-10-07  8:08     ` Pierre-Marie de Rodat
  0 siblings, 0 replies; 20+ messages in thread
From: Pierre-Marie de Rodat @ 2014-10-07  8:08 UTC (permalink / raw)
  To: Jason Merrill, GCC Patches; +Cc: Jakub Jelinek

On 10/03/2014 06:41 PM, Jason Merrill wrote:
> Patches 1-4 are OK.
>
>> +  bool pell_conversions = true;
>
> I don't understand "pell".  Do you mean "strip"?

Absolutely: I though it was correct English. I replaced all occurences 
of "pell" with "strip". Updates patches will follow...

Thank you very much for your review! :-)

-- 
Pierre-Marie de Rodat

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] Enhance array types debug info. for Ada
  2014-10-03  9:19 ` [PATCH] " Jakub Jelinek
  2014-10-03  9:20   ` Jakub Jelinek
@ 2014-10-07  8:08   ` Pierre-Marie de Rodat
  2014-10-07  8:29     ` Jakub Jelinek
  1 sibling, 1 reply; 20+ messages in thread
From: Pierre-Marie de Rodat @ 2014-10-07  8:08 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 5069 bytes --]

Jakub,

First, thank you very much for reviewing this set of patches.

I think it's better to start with an answer to your last mail:

On 10/03/2014 11:20 AM, Jakub Jelinek wrote:
> What kind of more complex expressions do you need and why?

GNAT can produce array types that make sense only as part of a record 
type and whose bounds are equal to members of this record type. Such 
ARRAY_TYPE nodes get generated from the kind of example you could see on 
the Dwarf-Discuss mailing list:

     type Array_Type is array (Integer range <>) of Integer;
     type Record_Type (N : Integer) is record
        A : Array_Type (1 .. N);
     end record;

In this case, the "A" field's type is an ARRAY_TYPE node whose upper 
bound is:

     COMPONENT_REF (PLACEHOLDER_EXPR (<Record_Type>),
                    FIELD_DECL("N"))

Upcoming patches will actually extend the need to handle more complex 
expressions: Ada arrays can contain dynamically-sized objects (their 
size is bounded, though). As a consequence, debuggers need these arrays 
to have a DW_AT_byte_stride attribute in order to decode them. The size 
expressions that describe the array stride in GCC can contain fairly 
complex operations such as unsigned divisions, unsigned comparisons, 
bitwise operations, calls to size functions (see 
stor-layout.c:self_referencial_size).

On 10/03/2014 11:18 AM, Jakub Jelinek wrote:
>> + /* Instead of producing a dedicated DW_TAG_array_type DIE for  this type, let
>> +    the circuitry wrap the main variant with DIEs for qualifiers  (for
>> +    instance: DW_TAG_const_type, ...). */
>> + if (type != TYPE_MAIN_VARIANT (type))
>> +     {
>> +       gen_type_die (TYPE_MAIN_VARIANT (type), context_die);
>> +       return;
>> +     }
>
> I don't like this, can you explain why? I'd say that if you only
> want to see TYPE_MAIN_VARIANT here, it should be responsibility of
> the callers to ensure that.

Agreed. I have updated the patch to:

  1. remove this hunk;
  2. in gen_type_die_with_usage, which is the only caller, move the 
type_main_variant call on "type" right before the array descriptors 
handling.

>> @@ -19941,7 +19991,8 @@ gen_type_die_with_usage (tree type,  dw_die_ref context_die,
>>     /* If this is an array type with hidden descriptor, handle itfirst.  */
>>     if (!TREE_ASM_WRITTEN (type)
>>         && lang_hooks.types.get_array_descr_info
>> -      && lang_hooks.types.get_array_descr_info (type, &info)
>> +      && lang_hooks.types.get_array_descr_info (type,
>> +						init_array_descr_info (&info))
>
> Just memset it to 0 instead?

Sure. I was not sure about whether is was considered good style, but 
it's done, now.

>> +  enum array_descr_ordering ordering;
>>     tree element_type;
>>     tree base_decl;
>>     tree data_location;
>>     tree allocated;
>>     tree associated;
>> +
>
> Why the extra vertical space?
>>     struct array_descr_dimen
>>       {

It made the separation between "global" and "dimension-local" 
information clearer to me. As I suppose you don't like it and as there 
is already one indentation level, I removed it.

>> 	* dwarf2out.c (gen_type_die_with_usage): Enable the array lang-hook
>> 	even when (dwarf_version < 3 && dwarf_strict).
>> 	(gen_descr_array_die): Do not output DW_AT_data_locationn,
>> 	DW_AT_associated, DW_AT_allocated and DW_AT_byte_stride DWARF
>> 	attributes when (dwarf_version < 3 && dwarf_strict).
>
> This patch sounds very wrong.  DW_OP_push_object_address is not in DWARF2
> either, and that is the basis of all the fields, so there is reallynothing
> you can really output correctly for DWARF2.  It isn't the default on sane
> targets, where GCC defaults to DWARF4 these days, so why bother?

Generating DW_OP_push_object_address in strict DWARF2 mode is indeed a 
bug (patch is adjusted). However, if I understand correctly all 
fields/attributes don't have to rely on it.

In the case of the first Ada example I quoted above, such an operation 
would not be emitted: instead, add_bound_info/add_scalar_info are going 
to output a DW_AT_upper_bound attribute that is a reference to another 
DIE. This is valid DWARF2 and, I think, justifies enabling the language 
hook in this case.

We have several platforms whose default to strict DWARF2. These are 
quite used platforms on which some DWARF consumers crash when provided 
DIEs and tags they do not handle.

>> gcc/fortran/
>> 	* trans-types.c (gfc_get_array_descr_info): Use PLACEHOLDER_EXPR nodes
>> 	instead of VAR_DECL ones in type-related expressions.  Remove base_decl
>> 	initialization.
>
> Ugh, I must say I don't like PLACEHOLDER_EXPRs at all.

Why so? I know that as far as supported front-ends are concerned, 
PLACEHOLDE_EXPR nodes are used only in GNAT, but it seems to me they 
describe the best what object the bound/stride/allocated/associated 
expressions (self-)reference.

I have attached to this mail the 3 patches that are updated thanks to 
your (Jakub and Jason's) comments and run successfuly the GCC testsuite 
on x86_64-pc-linux-gnu.

Thanks again for revewing!

-- 
Pierre-Marie de Rodat

[-- Attachment #2: gcc-0001-Complete-information-generated-through-the-array-des.patch --]
[-- Type: text/x-diff, Size: 6094 bytes --]

From 5ae605a24f0df5a8963fa84d0c07c278542977f1 Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Wed, 5 Feb 2014 12:00:02 +0100
Subject: [PATCH 1/5] Complete information generated through the array
 descriptor language hook

gcc/
	* dwarf2out.h (enum array_descr_ordering): New.
	(array_descr_dimen): Add a bounds_type structure field.
	(struct array_descr_info): Add a field to hold index type information
	and another one to hold ordering information.
	* dwarf2out.c (gen_type_die_with_usage): Get the main variant before
	invoking the array descriptor language hook.  Initialize the
	array_descr_info structure before calling the lang-hook.
	(gen_descr_array_type_die): Use gen_type_die if not processing the
	main type variant.  Replace Fortran-specific code with generic one
	using this new field.  Add a GNAT descriptive type, if any.  Output
	type information for the array bound subrange, if any.

gcc/fortran
	* trans-types.c (gfc_get_array_descr_info): Describe all Fortran
	arrays with column major ordering.
---
 gcc/dwarf2out.c           |   52 +++++++++++++++++++++++++++++----------------
 gcc/dwarf2out.h           |   12 +++++++++++
 gcc/fortran/trans-types.c |    1 +
 3 files changed, 47 insertions(+), 18 deletions(-)

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 59c05ed..39b859e 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -17401,18 +17401,25 @@ static void
 gen_descr_array_type_die (tree type, struct array_descr_info *info,
 			  dw_die_ref context_die)
 {
-  dw_die_ref scope_die = scope_die_for (type, context_die);
-  dw_die_ref array_die;
+  const dw_die_ref scope_die = scope_die_for (type, context_die);
+  const dw_die_ref array_die = new_die (DW_TAG_array_type, scope_die, type);
   int dim;
 
-  array_die = new_die (DW_TAG_array_type, scope_die, type);
   add_name_attribute (array_die, type_tag (type));
   equate_type_number_to_die (type, array_die);
 
-  /* For Fortran multidimensional arrays use DW_ORD_col_major ordering.  */
-  if (is_fortran ()
-      && info->ndimensions >= 2)
-    add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major);
+  if (info->ndimensions > 1)
+    switch (info->ordering)
+      {
+      case array_descr_ordering_row_major:
+	add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_row_major);
+	break;
+      case array_descr_ordering_column_major:
+	add_AT_unsigned (array_die, DW_AT_ordering, DW_ORD_col_major);
+	break;
+      default:
+	break;
+      }
 
   if (info->data_location)
     add_descr_info_field (array_die, DW_AT_data_location, info->data_location,
@@ -17424,11 +17431,17 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
     add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
 			  info->base_decl);
 
+  add_gnat_descriptive_type_attribute (array_die, type, context_die);
+
   for (dim = 0; dim < info->ndimensions; dim++)
     {
       dw_die_ref subrange_die
 	= new_die (DW_TAG_subrange_type, array_die, NULL);
 
+      if (info->dimen[dim].bounds_type)
+	add_type_attribute (subrange_die,
+			    info->dimen[dim].bounds_type, 0,
+			    context_die);
       if (info->dimen[dim].lower_bound)
 	{
 	  /* If it is the default value, omit it.  */
@@ -19986,17 +19999,6 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
       return;
     }
 
-  /* If this is an array type with hidden descriptor, handle it first.  */
-  if (!TREE_ASM_WRITTEN (type)
-      && lang_hooks.types.get_array_descr_info
-      && lang_hooks.types.get_array_descr_info (type, &info)
-      && (dwarf_version >= 3 || !dwarf_strict))
-    {
-      gen_descr_array_type_die (type, &info, context_die);
-      TREE_ASM_WRITTEN (type) = 1;
-      return;
-    }
-
   /* We are going to output a DIE to represent the unqualified version
      of this type (i.e. without any const or volatile qualifiers) so
      get the main variant (i.e. the unqualified version) of this type
@@ -20005,6 +20007,20 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
   if (TREE_CODE (type) != VECTOR_TYPE)
     type = type_main_variant (type);
 
+  /* If this is an array type with hidden descriptor, handle it first.  */
+  if (!TREE_ASM_WRITTEN (type)
+      && lang_hooks.types.get_array_descr_info
+      && (dwarf_version >= 3 || !dwarf_strict))
+    {
+      memset (&info, 0, sizeof (info));
+      if (lang_hooks.types.get_array_descr_info (type, &info))
+	{
+	  gen_descr_array_type_die (type, &info, context_die);
+	  TREE_ASM_WRITTEN (type) = 1;
+	  return;
+	}
+    }
+
   if (TREE_ASM_WRITTEN (type))
     return;
 
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 7843e0a..0cf290c 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -261,9 +261,17 @@ extern void dwarf2out_set_demangle_name_func (const char *(*) (const char *));
 extern void dwarf2out_vms_debug_main_pointer (void);
 #endif
 
+enum array_descr_ordering
+{
+  array_descr_ordering_default,
+  array_descr_ordering_row_major,
+  array_descr_ordering_column_major
+};
+
 struct array_descr_info
 {
   int ndimensions;
+  enum array_descr_ordering ordering;
   tree element_type;
   tree base_decl;
   tree data_location;
@@ -271,6 +279,10 @@ struct array_descr_info
   tree associated;
   struct array_descr_dimen
     {
+      /* GCC uses sizetype for array indices, so lower_bound and upper_bound
+	 will likely be "sizetype" values. However, bounds may have another
+	 type in the original source code.  */
+      tree bounds_type;
       tree lower_bound;
       tree upper_bound;
       tree stride;
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 6bfe14c..1bfe920 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -3036,6 +3036,7 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
 
   memset (info, '\0', sizeof (*info));
   info->ndimensions = rank;
+  info->ordering = array_descr_ordering_column_major;
   info->element_type = etype;
   ptype = build_pointer_type (gfc_array_index_type);
   base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
-- 
1.7.10.4


[-- Attachment #3: gcc-0002-Enable-the-array-descr-language-hook-for-all-DWARF-v.patch --]
[-- Type: text/x-diff, Size: 2850 bytes --]

From a292821505560a7a27b7446db6ed439360da940b Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Fri, 7 Feb 2014 16:09:21 +0100
Subject: [PATCH 2/5] Enable the array descr language hook for all DWARF
 versions

	* dwarf2out.c (gen_type_die_with_usage): Enable the array lang-hook
	even when (dwarf_version < 3 && dwarf_strict).
	(gen_descr_array_die): Do not output DW_AT_data_locationn,
	DW_AT_associated, DW_AT_allocated and DW_AT_byte_stride DWARF
	attributes when (dwarf_version < 3 && dwarf_strict).
---
 gcc/dwarf2out.c |   34 ++++++++++++++++++++--------------
 1 file changed, 20 insertions(+), 14 deletions(-)

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 39b859e..79cd8f5 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -17421,15 +17421,19 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 	break;
       }
 
-  if (info->data_location)
-    add_descr_info_field (array_die, DW_AT_data_location, info->data_location,
-			  info->base_decl);
-  if (info->associated)
-    add_descr_info_field (array_die, DW_AT_associated, info->associated,
-			  info->base_decl);
-  if (info->allocated)
-    add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
-			  info->base_decl);
+  if (dwarf_version >= 3 || !dwarf_strict)
+    {
+      if (info->data_location)
+	add_descr_info_field (array_die, DW_AT_data_location,
+			      info->data_location,
+			      info->base_decl);
+      if (info->associated)
+	add_descr_info_field (array_die, DW_AT_associated, info->associated,
+			      info->base_decl);
+      if (info->allocated)
+	add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
+			      info->base_decl);
+    }
 
   add_gnat_descriptive_type_attribute (array_die, type, context_die);
 
@@ -17460,10 +17464,13 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 	add_descr_info_field (subrange_die, DW_AT_upper_bound,
 			      info->dimen[dim].upper_bound,
 			      info->base_decl);
-      if (info->dimen[dim].stride)
-	add_descr_info_field (subrange_die, DW_AT_byte_stride,
-			      info->dimen[dim].stride,
-			      info->base_decl);
+      if (dwarf_version >= 3 || !dwarf_strict)
+	{
+	  if (info->dimen[dim].stride)
+	    add_descr_info_field (subrange_die, DW_AT_byte_stride,
+				  info->dimen[dim].stride,
+				  info->base_decl);
+	}
     }
 
   gen_type_die (info->element_type, context_die);
@@ -20010,7 +20017,6 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
   /* If this is an array type with hidden descriptor, handle it first.  */
   if (!TREE_ASM_WRITTEN (type)
       && lang_hooks.types.get_array_descr_info
-      && (dwarf_version >= 3 || !dwarf_strict))
     {
       memset (&info, 0, sizeof (info));
       if (lang_hooks.types.get_array_descr_info (type, &info))
-- 
1.7.10.4


[-- Attachment #4: gcc-0005-dwarf2out.c-do-not-short-circuit-add_bound_info-in-a.patch --]
[-- Type: text/x-diff, Size: 19662 bytes --]

From 7e09d1d93f8edcc556b21e4f39fcb3d3252b4f31 Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Mon, 9 Jun 2014 15:13:45 +0200
Subject: [PATCH 5/5] dwarf2out.c: do not short-circuit add_bound_info in
 array descr. lang-hook

gcc/
	* dwarf2out.h (struct array_descr_info): Remove the base_decl field.
	* dwarf2out.c (enum dw_scalar_form): New.
	(add_scalar_info): New.
	(loc_list_from_tree): Handle PLACEHOLDER_EXPR nodes for type-related
	expressions.
	(add_bound_info): Use add_scalar_info.
	(descr_info_loc): Remove.
	(add_descr_info_field): Remove.
	(gen_descr_array_type_die): Switch add_descr_info_field calls into
	add_scalar_info/add_bound_info ones.

gcc/ada
	* gcc-interface/misc.c (gnat_get_array_descr_info): Remove base_decl
	initialization.

gcc/fortran/
	* trans-types.c (gfc_get_array_descr_info): Use PLACEHOLDER_EXPR
	nodes instead of VAR_DECL ones in type-related expressions.  Remove
	base_decl initialization.
---
 gcc/ada/gcc-interface/misc.c |    1 -
 gcc/dwarf2out.c              |  438 ++++++++++++++++++++----------------------
 gcc/dwarf2out.h              |    1 -
 gcc/fortran/trans-types.c    |    7 +-
 4 files changed, 208 insertions(+), 239 deletions(-)

diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 7449ef9..0661d49 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -658,7 +658,6 @@ gnat_get_array_descr_info (const_tree type, struct array_descr_info *info)
   info->ordering = (convention_fortran_p
 		    ? array_descr_ordering_column_major
 		    : array_descr_ordering_row_major);
-  info->base_decl = NULL_TREE;
   info->data_location = NULL_TREE;
   info->allocated = NULL_TREE;
   info->associated = NULL_TREE;
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c334e9f..bd5fee2 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -2981,6 +2981,15 @@ static bool frame_pointer_fb_offset_valid;
 
 static vec<dw_die_ref> base_types;
 
+/* Flags to represent a set of attribute classes for attributes that represent
+   a scalar value (bounds, pointers, ...).  */
+enum dw_scalar_form
+{
+  dw_scalar_form_constant = 0x01,
+  dw_scalar_form_exprloc = 0x02,
+  dw_scalar_form_reference = 0x04
+};
+
 /* Forward declarations for functions defined in this file.  */
 
 static int is_pseudo_reg (const_rtx);
@@ -3186,6 +3195,7 @@ static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
 static void add_name_attribute (dw_die_ref, const char *);
 static void add_gnat_descriptive_type_attribute (dw_die_ref, tree, dw_die_ref);
 static void add_comp_dir_attribute (dw_die_ref);
+static void add_scalar_info (dw_die_ref, enum dwarf_attribute, tree, int);
 static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
 static void add_subscript_info (dw_die_ref, tree, bool);
 static void add_byte_size_attribute (dw_die_ref, tree);
@@ -14319,11 +14329,24 @@ loc_list_from_tree (tree loc, int want_address)
 
     case PLACEHOLDER_EXPR:
       /* This case involves extracting fields from an object to determine the
-	 position of other fields.  We don't try to encode this here.  The
-	 only user of this is Ada, which encodes the needed information using
-	 the names of types.  */
-      expansion_failed (loc, NULL_RTX, "PLACEHOLDER_EXPR");
-      return 0;
+	 position of other fields. It is supposed to appear only as the first
+	 operand of COMPONENT_REF nodes.  */
+      if (TREE_CODE (TREE_TYPE (loc)) == RECORD_TYPE
+	  && want_address >= 1)
+	{
+	  if (dwarf_version >= 3 || !dwarf_strict)
+	    {
+	      ret = new_loc_descr (DW_OP_push_object_address, 0, 0);
+	      have_address = 1;
+	      break;
+	    }
+	  else
+	    return NULL;
+	}
+      else
+	expansion_failed (loc, NULL_RTX,
+			  "PLACEHOLDER_EXPR for a non-structure");
+      break;
 
     case CALL_EXPR:
       expansion_failed (loc, NULL_RTX, "CALL_EXPR");
@@ -16432,6 +16455,141 @@ add_comp_dir_attribute (dw_die_ref die)
     add_AT_string (die, DW_AT_comp_dir, wd);
 }
 
+/* Given a tree node VALUE describing a scalar attribute ATTR (i.e. a bound, a
+   pointer computation, ...), output a representation for that bound according
+   to the accepted FORMS (see enum dw_scalar_form) and add it to DIE.  */
+
+static void
+add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
+		 int forms)
+{
+  dw_die_ref ctx, decl_die;
+  dw_loc_list_ref list;
+
+  bool strip_conversions = true;
+
+  while (strip_conversions)
+    switch (TREE_CODE (value))
+      {
+      case ERROR_MARK:
+      case SAVE_EXPR:
+	return;
+
+      CASE_CONVERT:
+      case VIEW_CONVERT_EXPR:
+	value = TREE_OPERAND (value, 0);
+	break;
+
+      default:
+	strip_conversions = false;
+	break;
+      }
+
+  /* If possible and permitted, output the attribute as a constant.  */
+  if ((forms & dw_scalar_form_constant) != 0
+      && TREE_CODE (value) == INTEGER_CST)
+    {
+      unsigned int prec = simple_type_size_in_bits (TREE_TYPE (value));
+
+      /* If HOST_WIDE_INT is big enough then represent the bound as
+	 a constant value.  We need to choose a form based on
+	 whether the type is signed or unsigned.  We cannot just
+	 call add_AT_unsigned if the value itself is positive
+	 (add_AT_unsigned might add the unsigned value encoded as
+	 DW_FORM_data[1248]).  Some DWARF consumers will lookup the
+	 bounds type and then sign extend any unsigned values found
+	 for signed types.  This is needed only for
+	 DW_AT_{lower,upper}_bound, since for most other attributes,
+	 consumers will treat DW_FORM_data[1248] as unsigned values,
+	 regardless of the underlying type.  */
+      if (prec <= HOST_BITS_PER_WIDE_INT
+	       || tree_fits_uhwi_p (value))
+	{
+	  if (TYPE_UNSIGNED (TREE_TYPE (value)))
+	    add_AT_unsigned (die, attr, TREE_INT_CST_LOW (value));
+	  else
+	    add_AT_int (die, attr, TREE_INT_CST_LOW (value));
+	}
+      else
+	/* Otherwise represent the bound as an unsigned value with
+	   the precision of its type.  The precision and signedness
+	   of the type will be necessary to re-interpret it
+	   unambiguously.  */
+	add_AT_wide (die, attr, value);
+    }
+
+  /* Otherwise, if it's possible and permitted too, output a reference to
+     another DIE.  */
+  if ((forms & dw_scalar_form_reference) != 0)
+    {
+      tree decl = NULL_TREE;
+
+      /* Some type attributes reference an outer type.  For instance, the upper
+	 bound of an array may reference an embedding record (this happens in
+	 Ada).  */
+      if (TREE_CODE (value) == COMPONENT_REF
+	  && TREE_CODE (TREE_OPERAND (value, 0)) == PLACEHOLDER_EXPR
+	  && TREE_CODE (TREE_OPERAND (value, 1)) == FIELD_DECL)
+	decl = TREE_OPERAND (value, 1);
+
+      else if (TREE_CODE (value) == VAR_DECL
+	       || TREE_CODE (value) == PARM_DECL
+	       || TREE_CODE (value) == RESULT_DECL)
+	decl = value;
+
+      if (decl != NULL_TREE)
+	{
+	  dw_die_ref decl_die = lookup_decl_die (decl);
+
+	  /* ??? Can this happen, or should the variable have been bound
+	     first?  Probably it can, since I imagine that we try to create
+	     the types of parameters in the order in which they exist in
+	     the list, and won't have created a forward reference to a
+	     later parameter.  */
+	  if (decl_die != NULL)
+	    {
+	      add_AT_die_ref (die, attr, decl_die);
+	      return;
+	    }
+	}
+    }
+
+  /* Last chance: try to create a stack operation procedure to evaluate the
+     value.  Do nothing if even that is not possible or permitted.  */
+  if ((forms & dw_scalar_form_exprloc) == 0)
+    return;
+
+  list = loc_list_from_tree (value, 2);
+  if (list == NULL || single_element_loc_list_p (list))
+    {
+      /* If this attribute is not a reference nor constant, it is
+	 a DWARF expression rather than location description.  For that
+	 loc_list_from_tree (value, 0) is needed.  */
+      dw_loc_list_ref list2 = loc_list_from_tree (value, 0);
+      if (list2 && single_element_loc_list_p (list2))
+	{
+	  add_AT_loc (die, attr, list2->expr);
+	  return;
+	}
+    }
+
+  /* If that failed to give a single element location list, fall back to
+     outputting this as a reference... still if permitted.  */
+  if (list == NULL || (forms & dw_scalar_form_reference) == 0)
+    return;
+
+  if (current_function_decl == 0)
+    ctx = comp_unit_die ();
+  else
+    ctx = lookup_decl_die (current_function_decl);
+
+  decl_die = new_die (DW_TAG_variable, ctx, value);
+  add_AT_flag (decl_die, DW_AT_artificial, 1);
+  add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, ctx);
+  add_AT_location_description (decl_die, DW_AT_location, list);
+  add_AT_die_ref (die, attr, decl_die);
+}
+
 /* Return the default for DW_AT_lower_bound, or -1 if there is not any
    default.  */
 
@@ -16473,121 +16631,40 @@ lower_bound_default (void)
    a representation for that bound.  */
 
 static void
-add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree bound)
+add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr,
+		tree bound)
 {
-  switch (TREE_CODE (bound))
-    {
-    case ERROR_MARK:
-      return;
+  int dflt;
 
-    /* All fixed-bounds are represented by INTEGER_CST nodes.  */
-    case INTEGER_CST:
+  while (1)
+    switch (TREE_CODE (bound))
       {
-	unsigned int prec = simple_type_size_in_bits (TREE_TYPE (bound));
-	int dflt;
+      /* Strip all conversions.  */
+      CASE_CONVERT:
+      case VIEW_CONVERT_EXPR:
+	bound = TREE_OPERAND (bound, 0);
+	break;
 
-	/* Use the default if possible.  */
+      /* All fixed-bounds are represented by INTEGER_CST nodes.  Lower bounds
+	 are even omitted when they are the default.  */
+      case INTEGER_CST:
+	/* If the value for this bound is the default one, we can even omit the
+	   attribute.  */
 	if (bound_attr == DW_AT_lower_bound
 	    && tree_fits_shwi_p (bound)
 	    && (dflt = lower_bound_default ()) != -1
 	    && tree_to_shwi (bound) == dflt)
-	  ;
-
-	/* If HOST_WIDE_INT is big enough then represent the bound as
-	   a constant value.  We need to choose a form based on
-	   whether the type is signed or unsigned.  We cannot just
-	   call add_AT_unsigned if the value itself is positive
-	   (add_AT_unsigned might add the unsigned value encoded as
-	   DW_FORM_data[1248]).  Some DWARF consumers will lookup the
-	   bounds type and then sign extend any unsigned values found
-	   for signed types.  This is needed only for
-	   DW_AT_{lower,upper}_bound, since for most other attributes,
-	   consumers will treat DW_FORM_data[1248] as unsigned values,
-	   regardless of the underlying type.  */
-	else if (prec <= HOST_BITS_PER_WIDE_INT
-		 || tree_fits_uhwi_p (bound))
-	  {
-	    if (TYPE_UNSIGNED (TREE_TYPE (bound)))
-	      add_AT_unsigned (subrange_die, bound_attr,
-			       TREE_INT_CST_LOW (bound));
-	    else
-	      add_AT_int (subrange_die, bound_attr, TREE_INT_CST_LOW (bound));
-	  }
-	else
-	  /* Otherwise represent the bound as an unsigned value with
-	     the precision of its type.  The precision and signedness
-	     of the type will be necessary to re-interpret it
-	     unambiguously.  */
-	  add_AT_wide (subrange_die, bound_attr, bound);
-      }
-      break;
-
-    CASE_CONVERT:
-    case VIEW_CONVERT_EXPR:
-      add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0));
-      break;
-
-    case SAVE_EXPR:
-      break;
-
-    case VAR_DECL:
-    case PARM_DECL:
-    case RESULT_DECL:
-      {
-	dw_die_ref decl_die = lookup_decl_die (bound);
-
-	/* ??? Can this happen, or should the variable have been bound
-	   first?  Probably it can, since I imagine that we try to create
-	   the types of parameters in the order in which they exist in
-	   the list, and won't have created a forward reference to a
-	   later parameter.  */
-	if (decl_die != NULL)
-	  {
-	    add_AT_die_ref (subrange_die, bound_attr, decl_die);
-	    break;
-	  }
-      }
-      /* FALLTHRU */
-
-    default:
-      {
-	/* Otherwise try to create a stack operation procedure to
-	   evaluate the value of the array bound.  */
-
-	dw_die_ref ctx, decl_die;
-	dw_loc_list_ref list;
-
-	list = loc_list_from_tree (bound, 2);
-	if (list == NULL || single_element_loc_list_p (list))
-	  {
-	    /* If DW_AT_*bound is not a reference nor constant, it is
-	       a DWARF expression rather than location description.
-	       For that loc_list_from_tree (bound, 0) is needed.
-	       If that fails to give a single element list,
-	       fall back to outputting this as a reference anyway.  */
-	    dw_loc_list_ref list2 = loc_list_from_tree (bound, 0);
-	    if (list2 && single_element_loc_list_p (list2))
-	      {
-		add_AT_loc (subrange_die, bound_attr, list2->expr);
-		break;
-	      }
-	  }
-	if (list == NULL)
-	  break;
+	  return;
 
-	if (current_function_decl == 0)
-	  ctx = comp_unit_die ();
-	else
-	  ctx = lookup_decl_die (current_function_decl);
+	/* FALLTHRU */
 
-	decl_die = new_die (DW_TAG_variable, ctx, bound);
-	add_AT_flag (decl_die, DW_AT_artificial, 1);
-	add_type_attribute (decl_die, TREE_TYPE (bound), TYPE_QUAL_CONST, ctx);
-	add_AT_location_description (decl_die, DW_AT_location, list);
-	add_AT_die_ref (subrange_die, bound_attr, decl_die);
-	break;
+      default:
+	add_scalar_info (subrange_die, bound_attr, bound,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference);
+	return;
       }
-    }
 }
 
 /* Add subscript info to TYPE_DIE, describing an array TYPE, collapsing
@@ -17375,99 +17452,6 @@ gen_array_type_die (tree type, dw_die_ref context_die)
     add_pubtype (type, array_die);
 }
 
-static dw_loc_descr_ref
-descr_info_loc (tree val, tree base_decl)
-{
-  HOST_WIDE_INT size;
-  dw_loc_descr_ref loc, loc2;
-  enum dwarf_location_atom op;
-
-  if (val == base_decl)
-    return new_loc_descr (DW_OP_push_object_address, 0, 0);
-
-  switch (TREE_CODE (val))
-    {
-    CASE_CONVERT:
-      return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-    case VAR_DECL:
-      return loc_descriptor_from_tree (val, 0);
-    case INTEGER_CST:
-      if (tree_fits_shwi_p (val))
-	return int_loc_descriptor (tree_to_shwi (val));
-      break;
-    case INDIRECT_REF:
-      size = int_size_in_bytes (TREE_TYPE (val));
-      if (size < 0)
-	break;
-      loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-      if (!loc)
-	break;
-      if (size == DWARF2_ADDR_SIZE)
-	add_loc_descr (&loc, new_loc_descr (DW_OP_deref, 0, 0));
-      else
-	add_loc_descr (&loc, new_loc_descr (DW_OP_deref_size, size, 0));
-      return loc;
-    case POINTER_PLUS_EXPR:
-    case PLUS_EXPR:
-      if (tree_fits_uhwi_p (TREE_OPERAND (val, 1))
-	  && tree_to_uhwi (TREE_OPERAND (val, 1)) < 16384)
-	{
-	  loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-	  if (!loc)
-	    break;
-	  loc_descr_plus_const (&loc, tree_to_shwi (TREE_OPERAND (val, 1)));
-	}
-      else
-	{
-	  op = DW_OP_plus;
-	do_binop:
-	  loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-	  if (!loc)
-	    break;
-	  loc2 = descr_info_loc (TREE_OPERAND (val, 1), base_decl);
-	  if (!loc2)
-	    break;
-	  add_loc_descr (&loc, loc2);
-	  add_loc_descr (&loc2, new_loc_descr (op, 0, 0));
-	}
-      return loc;
-    case MINUS_EXPR:
-      op = DW_OP_minus;
-      goto do_binop;
-    case MULT_EXPR:
-      op = DW_OP_mul;
-      goto do_binop;
-    case EQ_EXPR:
-      op = DW_OP_eq;
-      goto do_binop;
-    case NE_EXPR:
-      op = DW_OP_ne;
-      goto do_binop;
-    default:
-      break;
-    }
-  return NULL;
-}
-
-static void
-add_descr_info_field (dw_die_ref die, enum dwarf_attribute attr,
-		      tree val, tree base_decl)
-{
-  dw_loc_descr_ref loc;
-
-  if (tree_fits_shwi_p (val))
-    {
-      add_AT_unsigned (die, attr, tree_to_shwi (val));
-      return;
-    }
-
-  loc = descr_info_loc (val, base_decl);
-  if (!loc)
-    return;
-
-  add_AT_loc (die, attr, loc);
-}
-
 /* This routine generates DIE for array with hidden descriptor, details
    are filled into *info by a langhook.  */
 
@@ -17498,15 +17482,18 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
   if (dwarf_version >= 3 || !dwarf_strict)
     {
       if (info->data_location)
-	add_descr_info_field (array_die, DW_AT_data_location,
-			      info->data_location,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_data_location, info->data_location,
+			 dw_scalar_form_exprloc);
       if (info->associated)
-	add_descr_info_field (array_die, DW_AT_associated, info->associated,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_associated, info->associated,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference);
       if (info->allocated)
-	add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_allocated, info->allocated,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference);
     }
 
   add_gnat_descriptive_type_attribute (array_die, type, context_die);
@@ -17521,30 +17508,17 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 			    info->dimen[dim].bounds_type, 0,
 			    context_die);
       if (info->dimen[dim].lower_bound)
-	{
-	  /* If it is the default value, omit it.  */
-	  int dflt;
-
-	  if (tree_fits_shwi_p (info->dimen[dim].lower_bound)
-	      && (dflt = lower_bound_default ()) != -1
-	      && tree_to_shwi (info->dimen[dim].lower_bound) == dflt)
-	    ;
-	  else
-	    add_descr_info_field (subrange_die, DW_AT_lower_bound,
-				  info->dimen[dim].lower_bound,
-				  info->base_decl);
-	}
+	add_bound_info (subrange_die, DW_AT_lower_bound,
+			info->dimen[dim].lower_bound);
       if (info->dimen[dim].upper_bound)
-	add_descr_info_field (subrange_die, DW_AT_upper_bound,
-			      info->dimen[dim].upper_bound,
-			      info->base_decl);
-      if (dwarf_version >= 3 || !dwarf_strict)
-	{
-	  if (info->dimen[dim].stride)
-	    add_descr_info_field (subrange_die, DW_AT_byte_stride,
-				  info->dimen[dim].stride,
-				  info->base_decl);
-	}
+	add_bound_info (subrange_die, DW_AT_upper_bound,
+			info->dimen[dim].upper_bound);
+      if ((dwarf_version >= 3 || !dwarf_strict) && info->dimen[dim].stride)
+	add_scalar_info (subrange_die, DW_AT_byte_stride,
+			 info->dimen[dim].stride,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference);
     }
 
   gen_type_die (info->element_type, context_die);
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index a73fdb4..b37ba5c 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -274,7 +274,6 @@ struct array_descr_info
   int ndimensions;
   enum array_descr_ordering ordering;
   tree element_type;
-  tree base_decl;
   tree data_location;
   tree allocated;
   tree associated;
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 1bfe920..a108e81 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -3042,13 +3042,10 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
   base_decl = GFC_TYPE_ARRAY_BASE_DECL (type, indirect);
   if (!base_decl)
     {
-      base_decl = make_node (DEBUG_EXPR_DECL);
-      DECL_ARTIFICIAL (base_decl) = 1;
-      TREE_TYPE (base_decl) = indirect ? build_pointer_type (ptype) : ptype;
-      DECL_MODE (base_decl) = TYPE_MODE (TREE_TYPE (base_decl));
+      base_decl = build0 (PLACEHOLDER_EXPR,
+			  indirect ? build_pointer_type (ptype) : ptype);
       GFC_TYPE_ARRAY_BASE_DECL (type, indirect) = base_decl;
     }
-  info->base_decl = base_decl;
   if (indirect)
     base_decl = build1 (INDIRECT_REF, ptype, base_decl);
 
-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] Enhance array types debug info. for Ada
  2014-10-07  8:08   ` Pierre-Marie de Rodat
@ 2014-10-07  8:29     ` Jakub Jelinek
  2014-10-08 19:05       ` Pierre-Marie de Rodat
  0 siblings, 1 reply; 20+ messages in thread
From: Jakub Jelinek @ 2014-10-07  8:29 UTC (permalink / raw)
  To: Pierre-Marie de Rodat; +Cc: GCC Patches

On Tue, Oct 07, 2014 at 10:08:23AM +0200, Pierre-Marie de Rodat wrote:
> >>gcc/fortran/
> >>	* trans-types.c (gfc_get_array_descr_info): Use PLACEHOLDER_EXPR nodes
> >>	instead of VAR_DECL ones in type-related expressions.  Remove base_decl
> >>	initialization.
> >
> >Ugh, I must say I don't like PLACEHOLDER_EXPRs at all.
> 
> Why so? I know that as far as supported front-ends are concerned,
> PLACEHOLDE_EXPR nodes are used only in GNAT, but it seems to me they
> describe the best what object the bound/stride/allocated/associated
> expressions (self-)reference.

But isn't there a risk that you will have PLACEHOLDER_EXPRs (likely for Ada
only) in some trees not constructed by the langhook?
I mean, DW_OP_push_object_address isn't meaningful in all DWARF contexts,
in some it is forbidden, in others there is really no object to push, and as
implemented, you emit DW_OP_push_object_address (which emits the address of
a context related particular object) for any kind of PLACEHOLDER_EXPR with
RECORD_TYPE.

Thus, I'd feel safer, even if you decide to use a PLACEHOLDER_EXPR, that
the translation of that to DW_OP_push_object_address would be done only
if the PLACEHOLDER_EXPR is equal to some global variable, normally NULL,
and only changed temporarily while emitting loc for the array descriptor.
But then IMHO a DEBUG_EXPR_DECL is better.

That said, if Jason is fine with the patchset as is, I can live with it,
as other FEs don't use PLACEHOLDER_EXPRs, worst case it will affect Ada
only.
Also, please verify that with your patch the generated debug info for some
Fortran arrays is the same.

	Jakub

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] Enhance array types debug info. for Ada
  2014-10-07  8:29     ` Jakub Jelinek
@ 2014-10-08 19:05       ` Pierre-Marie de Rodat
  2014-10-22  8:55         ` [PING] " Pierre-Marie de Rodat
  2014-11-26 18:07         ` [PATCH] " Jakub Jelinek
  0 siblings, 2 replies; 20+ messages in thread
From: Pierre-Marie de Rodat @ 2014-10-08 19:05 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 2719 bytes --]

On 10/07/2014 10:29 AM, Jakub Jelinek wrote:
> But isn't there a risk that you will have PLACEHOLDER_EXPRs (likely for Ada
> only) in some trees not constructed by the langhook?
> I mean, DW_OP_push_object_address isn't meaningful in all DWARF contexts,
> in some it is forbidden, in others there is really no object to push, and as
> implemented, you emit DW_OP_push_object_address (which emits the address of
> a context related particular object) for any kind of PLACEHOLDER_EXPR with
> RECORD_TYPE.

Even with GNAT, this is not _supposed_ to happen. However during the 
development (for instance with LTO) I noticed cases where 
PLACEHOLDER_EXPR nodes were incorrectly used. Thanks to current work on 
the early debug info pass, such cases are doomed to disappear, but I 
completely agree with your point, so thank you for raising it. :-)

> Thus, I'd feel safer, even if you decide to use a PLACEHOLDER_EXPR, that
> the translation of that to DW_OP_push_object_address would be done only
> if the PLACEHOLDER_EXPR is equal to some global variable, normally NULL,
> and only changed temporarily while emitting loc for the array descriptor.

This is what the updated (and attached) patch does. Note that upcoming 
patches will enhance loc_list_from_tree (adding another parameter to 
loc_list_from_tree) and make it recurse to generate sub-expressions as 
DWARF procedures. Because of this kind recursion, I added a composite 
argument instead of relying on a global variable (so that "nested" 
contexts can exist at the same time).

> But then IMHO a DEBUG_EXPR_DECL is better.
> [...]
> Also, please verify that with your patch the generated debug info for some
> Fortran arrays is the same.

It's fortunate that you asked this since I wrongly assumed there was the 
corresponding testing in the GDB testsuite. As a matter of fact, support 
for Fortran's variable length arrays in GDB is still a work in progress 
so tests are not commited yet. So I used the Fortran example I could 
find there <http://intel-gdb.github.io/> instead and discovered that my 
patch did break debugging information for Fortran array types.

Fixing it while keeping a PLACEHOLDER_EXPR-based implementation seems a 
too heavy task for my little experience in the Fortran front-end and 
after having a closer look I agree with you: it seems less adapted to 
how things are currently done, there. So I finally leveraged this new 
composite argument to re-introduce the base_decl mechanism. 
DEBUG_EXPR_DECL is back in the Fortran front-end. ;-) Now, the same 
example keeps the same debugging information.

The latest patches bootstrapped well and passed successfully the GCC 
testsuite on x86_64-pc-linux-gnu.

-- 
Pierre-Marie de Rodat

[-- Attachment #2: gcc-0005-dwarf2out.c-do-not-short-circuit-add_bound_info-in-a.patch --]
[-- Type: text/x-diff, Size: 33396 bytes --]

From 794cafffae7202cd9ea8156bb7f7433a4e109e6c Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Mon, 9 Jun 2014 15:13:45 +0200
Subject: [PATCH 5/5] dwarf2out.c: do not short-circuit add_bound_info in
 array descr. lang-hook

gcc/
	* dwarf2out.h (struct array_descr_info): Remove the base_decl field.
	* dwarf2out.c (enum dw_scalar_form): New.
	(struct loc_descr_context): New.
	(add_scalar_info): New.
	(add_bound_info): Add a context parameter.  Use add_scalar_info.
	(loc_list_from_tree): Add a context parameter.  Handle PLACEHOLDER_EXPR
	nodes for type-related expressions.  Likewise for base declarations.
	(loc_descriptor_from_tree): Add a context parameter.
	(subrange_type_die): Update calls to add_bound_info.
	(tls_mem_loc_descriptor): Likewise.
	(loc_list_for_address_of_addr_expr_of_indirect_ref): Add a context
	parameter.  Update calls to loc_list_from_tree.
	(add_subscript_info): Update calls to add_bound_info.
	(gen_array_type_die): Update calls to loc_list_from_tree and to
	add_bound_info.
	(descr_info_loc): Remove.
	(add_descr_info_field): Remove.
	(gen_descr_array_type_die): Switch add_descr_info_field calls into
	add_scalar_info/add_bound_info ones.
	(gen_subprogram_die): Update calls to loc_list_from_tree.
	(gen_variable_die): Likewise.
---
 gcc/dwarf2out.c |  569 ++++++++++++++++++++++++++++---------------------------
 1 file changed, 294 insertions(+), 275 deletions(-)

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 3f3bdbb..30f429e 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -2981,6 +2981,15 @@ static bool frame_pointer_fb_offset_valid;
 
 static vec<dw_die_ref> base_types;
 
+/* Flags to represent a set of attribute classes for attributes that represent
+   a scalar value (bounds, pointers, ...).  */
+enum dw_scalar_form
+{
+  dw_scalar_form_constant = 0x01,
+  dw_scalar_form_exprloc = 0x02,
+  dw_scalar_form_reference = 0x04
+};
+
 /* Forward declarations for functions defined in this file.  */
 
 static int is_pseudo_reg (const_rtx);
@@ -3163,8 +3172,11 @@ static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx,
 					       enum var_init_status);
 static dw_loc_descr_ref loc_descriptor (rtx, enum machine_mode mode,
 					enum var_init_status);
-static dw_loc_list_ref loc_list_from_tree (tree, int);
-static dw_loc_descr_ref loc_descriptor_from_tree (tree, int);
+struct loc_descr_context;
+static dw_loc_list_ref loc_list_from_tree (tree, int,
+					   const struct loc_descr_context *);
+static dw_loc_descr_ref loc_descriptor_from_tree (tree, int,
+						  const struct loc_descr_context *);
 static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
 static tree field_type (const_tree);
 static unsigned int simple_type_align_in_bits (const_tree);
@@ -3186,7 +3198,10 @@ static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
 static void add_name_attribute (dw_die_ref, const char *);
 static void add_gnat_descriptive_type_attribute (dw_die_ref, tree, dw_die_ref);
 static void add_comp_dir_attribute (dw_die_ref);
-static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
+static void add_scalar_info (dw_die_ref, enum dwarf_attribute, tree, int,
+			     const struct loc_descr_context *);
+static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree,
+			    const struct loc_descr_context *);
 static void add_subscript_info (dw_die_ref, tree, bool);
 static void add_byte_size_attribute (dw_die_ref, tree);
 static void add_bit_offset_attribute (dw_die_ref, tree);
@@ -10515,9 +10530,9 @@ subrange_type_die (tree type, tree low, tree high, dw_die_ref context_die)
     }
 
   if (low)
-    add_bound_info (subrange_die, DW_AT_lower_bound, low);
+    add_bound_info (subrange_die, DW_AT_lower_bound, low, NULL);
   if (high)
-    add_bound_info (subrange_die, DW_AT_upper_bound, high);
+    add_bound_info (subrange_die, DW_AT_upper_bound, high, NULL);
 
   return subrange_die;
 }
@@ -11493,7 +11508,7 @@ tls_mem_loc_descriptor (rtx mem)
       || !DECL_THREAD_LOCAL_P (base))
     return NULL;
 
-  loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), 1);
+  loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), 1, NULL);
   if (loc_result == NULL)
     return NULL;
 
@@ -14231,10 +14246,13 @@ cst_pool_loc_descr (tree loc)
 
 /* Return dw_loc_list representing address of addr_expr LOC
    by looking for inner INDIRECT_REF expression and turning
-   it into simple arithmetics.  */
+   it into simple arithmetics.
+
+   See loc_list_from_tree for the meaning of CONTEXT.  */
 
 static dw_loc_list_ref
-loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
+loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev,
+						   const loc_descr_context *context)
 {
   tree obj, offset;
   HOST_WIDE_INT bitsize, bitpos, bytepos;
@@ -14258,18 +14276,19 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
       return 0;
     }
   if (!offset && !bitpos)
-    list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), toplev ? 2 : 1);
+    list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), toplev ? 2 : 1,
+				   context);
   else if (toplev
 	   && int_size_in_bytes (TREE_TYPE (loc)) <= DWARF2_ADDR_SIZE
 	   && (dwarf_version >= 4 || !dwarf_strict))
     {
-      list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), 0, context);
       if (!list_ret)
 	return 0;
       if (offset)
 	{
 	  /* Variable offset.  */
-	  list_ret1 = loc_list_from_tree (offset, 0);
+	  list_ret1 = loc_list_from_tree (offset, 0, context);
 	  if (list_ret1 == 0)
 	    return 0;
 	  add_loc_list (&list_ret, list_ret1);
@@ -14292,15 +14311,36 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
 }
 
 
+/* Helper structure for location descriptions generation.  */
+struct loc_descr_context
+{
+  /* The type that is implicitely referenced by DW_OP_push_object_address, or
+     NULL_TREE if DW_OP_push_object_address in invalid for this location
+     description.  This is used when processing PLACEHOLDER_EXPR nodes.  */
+  tree context_type;
+  /* The ..._DECL node that should be translated as a
+     DW_OP_push_object_address operation.  */
+  tree base_decl;
+};
+
 /* Generate Dwarf location list representing LOC.
    If WANT_ADDRESS is false, expression computing LOC will be computed
    If WANT_ADDRESS is 1, expression computing address of LOC will be returned
    if WANT_ADDRESS is 2, expression computing address useable in location
      will be returned (i.e. DW_OP_reg can be used
-     to refer to register values).  */
+     to refer to register values).
+
+   CONTEXT provides information to customize the location descriptions
+   generation.  Its context_type field specifies what type is implicitely
+   referenced by DW_OP_push_object_address.  If it is NULL_TREE, this operation
+   will not be generated.
+
+   If CONTEXT is NULL, the behavior is the same as if the context_type field
+   was NULL_TREE.  */
 
 static dw_loc_list_ref
-loc_list_from_tree (tree loc, int want_address)
+loc_list_from_tree (tree loc, int want_address,
+		    const struct loc_descr_context *context)
 {
   dw_loc_descr_ref ret = NULL, ret1 = NULL;
   dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
@@ -14311,6 +14351,12 @@ loc_list_from_tree (tree loc, int want_address)
      extending the values properly.  Hopefully this won't be a real
      problem...  */
 
+  if (context != NULL
+      && context->base_decl == loc
+      && want_address == 0)
+    return new_loc_list (new_loc_descr (DW_OP_push_object_address, 0, 0),
+			 NULL, NULL, NULL);
+
   switch (TREE_CODE (loc))
     {
     case ERROR_MARK:
@@ -14319,11 +14365,26 @@ loc_list_from_tree (tree loc, int want_address)
 
     case PLACEHOLDER_EXPR:
       /* This case involves extracting fields from an object to determine the
-	 position of other fields.  We don't try to encode this here.  The
-	 only user of this is Ada, which encodes the needed information using
-	 the names of types.  */
-      expansion_failed (loc, NULL_RTX, "PLACEHOLDER_EXPR");
-      return 0;
+	 position of other fields. It is supposed to appear only as the first
+         operand of COMPONENT_REF nodes and to reference precisely the type
+         that the context allows.  */
+      if (context != NULL
+          && TREE_TYPE (loc) == context->context_type
+	  && want_address >= 1)
+	{
+	  if (dwarf_version >= 3 || !dwarf_strict)
+	    {
+	      ret = new_loc_descr (DW_OP_push_object_address, 0, 0);
+	      have_address = 1;
+	      break;
+	    }
+	  else
+	    return NULL;
+	}
+      else
+	expansion_failed (loc, NULL_RTX,
+			  "PLACEHOLDER_EXPR for a unexpected type");
+      break;
 
     case CALL_EXPR:
       expansion_failed (loc, NULL_RTX, "CALL_EXPR");
@@ -14344,7 +14405,7 @@ loc_list_from_tree (tree loc, int want_address)
       if (want_address)
 	{
 	  list_ret = loc_list_for_address_of_addr_expr_of_indirect_ref
-		       (loc, want_address == 2);
+		       (loc, want_address == 2, context);
 	  if (list_ret)
 	    have_address = 1;
 	  else if (decl_address_ip_invariant_p (TREE_OPERAND (loc, 0))
@@ -14353,7 +14414,7 @@ loc_list_from_tree (tree loc, int want_address)
 	}
         /* Otherwise, process the argument and look for the address.  */
       if (!list_ret && !ret)
-        list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 1);
+        list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 1, context);
       else
 	{
 	  if (want_address)
@@ -14423,7 +14484,7 @@ loc_list_from_tree (tree loc, int want_address)
     case RESULT_DECL:
       if (DECL_HAS_VALUE_EXPR_P (loc))
 	return loc_list_from_tree (DECL_VALUE_EXPR (loc),
-				   want_address);
+				   want_address, context);
       /* FALLTHRU */
 
     case FUNCTION_DECL:
@@ -14497,7 +14558,7 @@ loc_list_from_tree (tree loc, int want_address)
 	}
       /* Fallthru.  */
     case INDIRECT_REF:
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
       have_address = 1;
       break;
 
@@ -14506,13 +14567,13 @@ loc_list_from_tree (tree loc, int want_address)
       return NULL;
 
     case COMPOUND_EXPR:
-      return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address);
+      return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address, context);
 
     CASE_CONVERT:
     case VIEW_CONVERT_EXPR:
     case SAVE_EXPR:
     case MODIFY_EXPR:
-      return loc_list_from_tree (TREE_OPERAND (loc, 0), want_address);
+      return loc_list_from_tree (TREE_OPERAND (loc, 0), want_address, context);
 
     case COMPONENT_REF:
     case BIT_FIELD_REF:
@@ -14533,7 +14594,8 @@ loc_list_from_tree (tree loc, int want_address)
 
 	list_ret = loc_list_from_tree (obj,
 				       want_address == 2
-				       && !bitpos && !offset ? 2 : 1);
+				       && !bitpos && !offset ? 2 : 1,
+                                       context);
 	/* TODO: We can extract value of the small expression via shifting even
 	   for nonzero bitpos.  */
 	if (list_ret == 0)
@@ -14548,7 +14610,7 @@ loc_list_from_tree (tree loc, int want_address)
 	if (offset != NULL_TREE)
 	  {
 	    /* Variable offset.  */
-	    list_ret1 = loc_list_from_tree (offset, 0);
+	    list_ret1 = loc_list_from_tree (offset, 0, context);
 	    if (list_ret1 == 0)
 	      return 0;
 	    add_loc_list (&list_ret, list_ret1);
@@ -14638,8 +14700,8 @@ loc_list_from_tree (tree loc, int want_address)
 	  op = DW_OP_mod;
 	  goto do_binop;
 	}
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
-      list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
+      list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0, context);
       if (list_ret == 0 || list_ret1 == 0)
 	return 0;
 
@@ -14670,7 +14732,7 @@ loc_list_from_tree (tree loc, int want_address)
     do_plus:
       if (tree_fits_shwi_p (TREE_OPERAND (loc, 1)))
 	{
-	  list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+	  list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
 	  if (list_ret == 0)
 	    return 0;
 
@@ -14718,8 +14780,8 @@ loc_list_from_tree (tree loc, int want_address)
       goto do_binop;
 
     do_binop:
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
-      list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
+      list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0, context);
       if (list_ret == 0 || list_ret1 == 0)
 	return 0;
 
@@ -14743,7 +14805,7 @@ loc_list_from_tree (tree loc, int want_address)
       goto do_unop;
 
     do_unop:
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
       if (list_ret == 0)
 	return 0;
 
@@ -14767,12 +14829,12 @@ loc_list_from_tree (tree loc, int want_address)
     case COND_EXPR:
       {
 	dw_loc_descr_ref lhs
-	  = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
+	  = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0, context);
 	dw_loc_list_ref rhs
-	  = loc_list_from_tree (TREE_OPERAND (loc, 2), 0);
+	  = loc_list_from_tree (TREE_OPERAND (loc, 2), 0, context);
 	dw_loc_descr_ref bra_node, jump_node, tmp;
 
-	list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+	list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
 	if (list_ret == 0 || lhs == 0 || rhs == 0)
 	  return 0;
 
@@ -14878,9 +14940,10 @@ loc_list_from_tree (tree loc, int want_address)
 
 /* Same as above but return only single location expression.  */
 static dw_loc_descr_ref
-loc_descriptor_from_tree (tree loc, int want_address)
+loc_descriptor_from_tree (tree loc, int want_address,
+			  const struct loc_descr_context *context)
 {
-  dw_loc_list_ref ret = loc_list_from_tree (loc, want_address);
+  dw_loc_list_ref ret = loc_list_from_tree (loc, want_address, context);
   if (!ret)
     return NULL;
   if (ret->dw_loc_next)
@@ -15940,7 +16003,8 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
     }
   if (list == NULL)
     {
-      list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2);
+      list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2,
+				 NULL);
       /* It is usually worth caching this result if the decl is from
 	 BLOCK_NONLOCALIZED_VARS and if the list has at least two elements.  */
       if (cache_p && list && list->dw_loc_next)
@@ -16432,6 +16496,142 @@ add_comp_dir_attribute (dw_die_ref die)
     add_AT_string (die, DW_AT_comp_dir, wd);
 }
 
+/* Given a tree node VALUE describing a scalar attribute ATTR (i.e. a bound, a
+   pointer computation, ...), output a representation for that bound according
+   to the accepted FORMS (see enum dw_scalar_form) and add it to DIE.  See
+   loc_list_from_tree for the meaning of CONTEXT.  */
+
+static void
+add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
+		 int forms, const struct loc_descr_context *context)
+{
+  dw_die_ref ctx, decl_die;
+  dw_loc_list_ref list;
+
+  bool strip_conversions = true;
+
+  while (strip_conversions)
+    switch (TREE_CODE (value))
+      {
+      case ERROR_MARK:
+      case SAVE_EXPR:
+	return;
+
+      CASE_CONVERT:
+      case VIEW_CONVERT_EXPR:
+	value = TREE_OPERAND (value, 0);
+	break;
+
+      default:
+	strip_conversions = false;
+	break;
+      }
+
+  /* If possible and permitted, output the attribute as a constant.  */
+  if ((forms & dw_scalar_form_constant) != 0
+      && TREE_CODE (value) == INTEGER_CST)
+    {
+      unsigned int prec = simple_type_size_in_bits (TREE_TYPE (value));
+
+      /* If HOST_WIDE_INT is big enough then represent the bound as
+	 a constant value.  We need to choose a form based on
+	 whether the type is signed or unsigned.  We cannot just
+	 call add_AT_unsigned if the value itself is positive
+	 (add_AT_unsigned might add the unsigned value encoded as
+	 DW_FORM_data[1248]).  Some DWARF consumers will lookup the
+	 bounds type and then sign extend any unsigned values found
+	 for signed types.  This is needed only for
+	 DW_AT_{lower,upper}_bound, since for most other attributes,
+	 consumers will treat DW_FORM_data[1248] as unsigned values,
+	 regardless of the underlying type.  */
+      if (prec <= HOST_BITS_PER_WIDE_INT
+	       || tree_fits_uhwi_p (value))
+	{
+	  if (TYPE_UNSIGNED (TREE_TYPE (value)))
+	    add_AT_unsigned (die, attr, TREE_INT_CST_LOW (value));
+	  else
+	    add_AT_int (die, attr, TREE_INT_CST_LOW (value));
+	}
+      else
+	/* Otherwise represent the bound as an unsigned value with
+	   the precision of its type.  The precision and signedness
+	   of the type will be necessary to re-interpret it
+	   unambiguously.  */
+	add_AT_wide (die, attr, value);
+    }
+
+  /* Otherwise, if it's possible and permitted too, output a reference to
+     another DIE.  */
+  if ((forms & dw_scalar_form_reference) != 0)
+    {
+      tree decl = NULL_TREE;
+
+      /* Some type attributes reference an outer type.  For instance, the upper
+	 bound of an array may reference an embedding record (this happens in
+	 Ada).  */
+      if (TREE_CODE (value) == COMPONENT_REF
+	  && TREE_CODE (TREE_OPERAND (value, 0)) == PLACEHOLDER_EXPR
+	  && TREE_CODE (TREE_OPERAND (value, 1)) == FIELD_DECL)
+	decl = TREE_OPERAND (value, 1);
+
+      else if (TREE_CODE (value) == VAR_DECL
+	       || TREE_CODE (value) == PARM_DECL
+	       || TREE_CODE (value) == RESULT_DECL)
+	decl = value;
+
+      if (decl != NULL_TREE)
+	{
+	  dw_die_ref decl_die = lookup_decl_die (decl);
+
+	  /* ??? Can this happen, or should the variable have been bound
+	     first?  Probably it can, since I imagine that we try to create
+	     the types of parameters in the order in which they exist in
+	     the list, and won't have created a forward reference to a
+	     later parameter.  */
+	  if (decl_die != NULL)
+	    {
+	      add_AT_die_ref (die, attr, decl_die);
+	      return;
+	    }
+	}
+    }
+
+  /* Last chance: try to create a stack operation procedure to evaluate the
+     value.  Do nothing if even that is not possible or permitted.  */
+  if ((forms & dw_scalar_form_exprloc) == 0)
+    return;
+
+  list = loc_list_from_tree (value, 2, context);
+  if (list == NULL || single_element_loc_list_p (list))
+    {
+      /* If this attribute is not a reference nor constant, it is
+	 a DWARF expression rather than location description.  For that
+	 loc_list_from_tree (value, 0, &context) is needed.  */
+      dw_loc_list_ref list2 = loc_list_from_tree (value, 0, context);
+      if (list2 && single_element_loc_list_p (list2))
+	{
+	  add_AT_loc (die, attr, list2->expr);
+	  return;
+	}
+    }
+
+  /* If that failed to give a single element location list, fall back to
+     outputting this as a reference... still if permitted.  */
+  if (list == NULL || (forms & dw_scalar_form_reference) == 0)
+    return;
+
+  if (current_function_decl == 0)
+    ctx = comp_unit_die ();
+  else
+    ctx = lookup_decl_die (current_function_decl);
+
+  decl_die = new_die (DW_TAG_variable, ctx, value);
+  add_AT_flag (decl_die, DW_AT_artificial, 1);
+  add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, ctx);
+  add_AT_location_description (decl_die, DW_AT_location, list);
+  add_AT_die_ref (die, attr, decl_die);
+}
+
 /* Return the default for DW_AT_lower_bound, or -1 if there is not any
    default.  */
 
@@ -16473,121 +16673,41 @@ lower_bound_default (void)
    a representation for that bound.  */
 
 static void
-add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree bound)
+add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr,
+		tree bound, const struct loc_descr_context *context)
 {
-  switch (TREE_CODE (bound))
-    {
-    case ERROR_MARK:
-      return;
+  int dflt;
 
-    /* All fixed-bounds are represented by INTEGER_CST nodes.  */
-    case INTEGER_CST:
+  while (1)
+    switch (TREE_CODE (bound))
       {
-	unsigned int prec = simple_type_size_in_bits (TREE_TYPE (bound));
-	int dflt;
+      /* Strip all conversions.  */
+      CASE_CONVERT:
+      case VIEW_CONVERT_EXPR:
+	bound = TREE_OPERAND (bound, 0);
+	break;
 
-	/* Use the default if possible.  */
+      /* All fixed-bounds are represented by INTEGER_CST nodes.  Lower bounds
+	 are even omitted when they are the default.  */
+      case INTEGER_CST:
+	/* If the value for this bound is the default one, we can even omit the
+	   attribute.  */
 	if (bound_attr == DW_AT_lower_bound
 	    && tree_fits_shwi_p (bound)
 	    && (dflt = lower_bound_default ()) != -1
 	    && tree_to_shwi (bound) == dflt)
-	  ;
-
-	/* If HOST_WIDE_INT is big enough then represent the bound as
-	   a constant value.  We need to choose a form based on
-	   whether the type is signed or unsigned.  We cannot just
-	   call add_AT_unsigned if the value itself is positive
-	   (add_AT_unsigned might add the unsigned value encoded as
-	   DW_FORM_data[1248]).  Some DWARF consumers will lookup the
-	   bounds type and then sign extend any unsigned values found
-	   for signed types.  This is needed only for
-	   DW_AT_{lower,upper}_bound, since for most other attributes,
-	   consumers will treat DW_FORM_data[1248] as unsigned values,
-	   regardless of the underlying type.  */
-	else if (prec <= HOST_BITS_PER_WIDE_INT
-		 || tree_fits_uhwi_p (bound))
-	  {
-	    if (TYPE_UNSIGNED (TREE_TYPE (bound)))
-	      add_AT_unsigned (subrange_die, bound_attr,
-			       TREE_INT_CST_LOW (bound));
-	    else
-	      add_AT_int (subrange_die, bound_attr, TREE_INT_CST_LOW (bound));
-	  }
-	else
-	  /* Otherwise represent the bound as an unsigned value with
-	     the precision of its type.  The precision and signedness
-	     of the type will be necessary to re-interpret it
-	     unambiguously.  */
-	  add_AT_wide (subrange_die, bound_attr, bound);
-      }
-      break;
-
-    CASE_CONVERT:
-    case VIEW_CONVERT_EXPR:
-      add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0));
-      break;
-
-    case SAVE_EXPR:
-      break;
-
-    case VAR_DECL:
-    case PARM_DECL:
-    case RESULT_DECL:
-      {
-	dw_die_ref decl_die = lookup_decl_die (bound);
-
-	/* ??? Can this happen, or should the variable have been bound
-	   first?  Probably it can, since I imagine that we try to create
-	   the types of parameters in the order in which they exist in
-	   the list, and won't have created a forward reference to a
-	   later parameter.  */
-	if (decl_die != NULL)
-	  {
-	    add_AT_die_ref (subrange_die, bound_attr, decl_die);
-	    break;
-	  }
-      }
-      /* FALLTHRU */
-
-    default:
-      {
-	/* Otherwise try to create a stack operation procedure to
-	   evaluate the value of the array bound.  */
-
-	dw_die_ref ctx, decl_die;
-	dw_loc_list_ref list;
-
-	list = loc_list_from_tree (bound, 2);
-	if (list == NULL || single_element_loc_list_p (list))
-	  {
-	    /* If DW_AT_*bound is not a reference nor constant, it is
-	       a DWARF expression rather than location description.
-	       For that loc_list_from_tree (bound, 0) is needed.
-	       If that fails to give a single element list,
-	       fall back to outputting this as a reference anyway.  */
-	    dw_loc_list_ref list2 = loc_list_from_tree (bound, 0);
-	    if (list2 && single_element_loc_list_p (list2))
-	      {
-		add_AT_loc (subrange_die, bound_attr, list2->expr);
-		break;
-	      }
-	  }
-	if (list == NULL)
-	  break;
+	  return;
 
-	if (current_function_decl == 0)
-	  ctx = comp_unit_die ();
-	else
-	  ctx = lookup_decl_die (current_function_decl);
+	/* FALLTHRU */
 
-	decl_die = new_die (DW_TAG_variable, ctx, bound);
-	add_AT_flag (decl_die, DW_AT_artificial, 1);
-	add_type_attribute (decl_die, TREE_TYPE (bound), TYPE_QUAL_CONST, ctx);
-	add_AT_location_description (decl_die, DW_AT_location, list);
-	add_AT_die_ref (subrange_die, bound_attr, decl_die);
-	break;
+      default:
+	add_scalar_info (subrange_die, bound_attr, bound,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference,
+			 context);
+	return;
       }
-    }
 }
 
 /* Add subscript info to TYPE_DIE, describing an array TYPE, collapsing
@@ -16644,9 +16764,9 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
 	     to produce useful results, go ahead and output the lower
 	     bound solo, and hope the debugger can cope.  */
 
-	  add_bound_info (subrange_die, DW_AT_lower_bound, lower);
+	  add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL);
 	  if (upper)
-	    add_bound_info (subrange_die, DW_AT_upper_bound, upper);
+	    add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL);
 	}
 
       /* Otherwise we have an array type with an unspecified length.  The
@@ -17305,7 +17425,7 @@ gen_array_type_die (tree type, dw_die_ref context_die)
 	       && DECL_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
 	{
 	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
-	  dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2);
+	  dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2, NULL);
 
 	  size = int_size_in_bytes (TREE_TYPE (szdecl));
 	  if (loc && size > 0)
@@ -17347,9 +17467,9 @@ gen_array_type_die (tree type, dw_die_ref context_die)
     {
       /* For VECTOR_TYPEs we use an array die with appropriate bounds.  */
       dw_die_ref subrange_die = new_die (DW_TAG_subrange_type, array_die, NULL);
-      add_bound_info (subrange_die, DW_AT_lower_bound, size_zero_node);
+      add_bound_info (subrange_die, DW_AT_lower_bound, size_zero_node, NULL);
       add_bound_info (subrange_die, DW_AT_upper_bound,
-		      size_int (TYPE_VECTOR_SUBPARTS (type) - 1));
+		      size_int (TYPE_VECTOR_SUBPARTS (type) - 1), NULL);
     }
   else
     add_subscript_info (array_die, type, collapse_nested_arrays);
@@ -17375,99 +17495,6 @@ gen_array_type_die (tree type, dw_die_ref context_die)
     add_pubtype (type, array_die);
 }
 
-static dw_loc_descr_ref
-descr_info_loc (tree val, tree base_decl)
-{
-  HOST_WIDE_INT size;
-  dw_loc_descr_ref loc, loc2;
-  enum dwarf_location_atom op;
-
-  if (val == base_decl)
-    return new_loc_descr (DW_OP_push_object_address, 0, 0);
-
-  switch (TREE_CODE (val))
-    {
-    CASE_CONVERT:
-      return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-    case VAR_DECL:
-      return loc_descriptor_from_tree (val, 0);
-    case INTEGER_CST:
-      if (tree_fits_shwi_p (val))
-	return int_loc_descriptor (tree_to_shwi (val));
-      break;
-    case INDIRECT_REF:
-      size = int_size_in_bytes (TREE_TYPE (val));
-      if (size < 0)
-	break;
-      loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-      if (!loc)
-	break;
-      if (size == DWARF2_ADDR_SIZE)
-	add_loc_descr (&loc, new_loc_descr (DW_OP_deref, 0, 0));
-      else
-	add_loc_descr (&loc, new_loc_descr (DW_OP_deref_size, size, 0));
-      return loc;
-    case POINTER_PLUS_EXPR:
-    case PLUS_EXPR:
-      if (tree_fits_uhwi_p (TREE_OPERAND (val, 1))
-	  && tree_to_uhwi (TREE_OPERAND (val, 1)) < 16384)
-	{
-	  loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-	  if (!loc)
-	    break;
-	  loc_descr_plus_const (&loc, tree_to_shwi (TREE_OPERAND (val, 1)));
-	}
-      else
-	{
-	  op = DW_OP_plus;
-	do_binop:
-	  loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-	  if (!loc)
-	    break;
-	  loc2 = descr_info_loc (TREE_OPERAND (val, 1), base_decl);
-	  if (!loc2)
-	    break;
-	  add_loc_descr (&loc, loc2);
-	  add_loc_descr (&loc2, new_loc_descr (op, 0, 0));
-	}
-      return loc;
-    case MINUS_EXPR:
-      op = DW_OP_minus;
-      goto do_binop;
-    case MULT_EXPR:
-      op = DW_OP_mul;
-      goto do_binop;
-    case EQ_EXPR:
-      op = DW_OP_eq;
-      goto do_binop;
-    case NE_EXPR:
-      op = DW_OP_ne;
-      goto do_binop;
-    default:
-      break;
-    }
-  return NULL;
-}
-
-static void
-add_descr_info_field (dw_die_ref die, enum dwarf_attribute attr,
-		      tree val, tree base_decl)
-{
-  dw_loc_descr_ref loc;
-
-  if (tree_fits_shwi_p (val))
-    {
-      add_AT_unsigned (die, attr, tree_to_shwi (val));
-      return;
-    }
-
-  loc = descr_info_loc (val, base_decl);
-  if (!loc)
-    return;
-
-  add_AT_loc (die, attr, loc);
-}
-
 /* This routine generates DIE for array with hidden descriptor, details
    are filled into *info by a langhook.  */
 
@@ -17477,6 +17504,7 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 {
   const dw_die_ref scope_die = scope_die_for (type, context_die);
   const dw_die_ref array_die = new_die (DW_TAG_array_type, scope_die, type);
+  const struct loc_descr_context context = { type, info->base_decl };
   int dim;
 
   add_name_attribute (array_die, type_tag (type));
@@ -17498,15 +17526,18 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
   if (dwarf_version >= 3 || !dwarf_strict)
     {
       if (info->data_location)
-	add_descr_info_field (array_die, DW_AT_data_location,
-			      info->data_location,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_data_location, info->data_location,
+			 dw_scalar_form_exprloc, &context);
       if (info->associated)
-	add_descr_info_field (array_die, DW_AT_associated, info->associated,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_associated, info->associated,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference, &context);
       if (info->allocated)
-	add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_allocated, info->allocated,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference, &context);
     }
 
   add_gnat_descriptive_type_attribute (array_die, type, context_die);
@@ -17521,30 +17552,18 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 			    info->dimen[dim].bounds_type, 0,
 			    context_die);
       if (info->dimen[dim].lower_bound)
-	{
-	  /* If it is the default value, omit it.  */
-	  int dflt;
-
-	  if (tree_fits_shwi_p (info->dimen[dim].lower_bound)
-	      && (dflt = lower_bound_default ()) != -1
-	      && tree_to_shwi (info->dimen[dim].lower_bound) == dflt)
-	    ;
-	  else
-	    add_descr_info_field (subrange_die, DW_AT_lower_bound,
-				  info->dimen[dim].lower_bound,
-				  info->base_decl);
-	}
+	add_bound_info (subrange_die, DW_AT_lower_bound,
+			info->dimen[dim].lower_bound, &context);
       if (info->dimen[dim].upper_bound)
-	add_descr_info_field (subrange_die, DW_AT_upper_bound,
-			      info->dimen[dim].upper_bound,
-			      info->base_decl);
-      if (dwarf_version >= 3 || !dwarf_strict)
-	{
-	  if (info->dimen[dim].stride)
-	    add_descr_info_field (subrange_die, DW_AT_byte_stride,
-				  info->dimen[dim].stride,
-				  info->base_decl);
-	}
+	add_bound_info (subrange_die, DW_AT_upper_bound,
+			info->dimen[dim].upper_bound, &context);
+      if ((dwarf_version >= 3 || !dwarf_strict) && info->dimen[dim].stride)
+	add_scalar_info (subrange_die, DW_AT_byte_stride,
+			 info->dimen[dim].stride,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference,
+			 &context);
     }
 
   gen_type_die (info->element_type, context_die);
@@ -18602,7 +18621,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 
       if (fun->static_chain_decl)
 	add_AT_location_description (subr_die, DW_AT_static_link,
-		 loc_list_from_tree (fun->static_chain_decl, 2));
+		 loc_list_from_tree (fun->static_chain_decl, 2, NULL));
     }
 
   /* Generate child dies for template paramaters.  */
@@ -18933,7 +18952,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
 	{
 	  if (get_AT (var_die, DW_AT_location) == NULL)
 	    {
-	      loc = loc_list_from_tree (com_decl, off ? 1 : 2);
+	      loc = loc_list_from_tree (com_decl, off ? 1 : 2, NULL);
 	      if (loc)
 		{
 		  if (off)
@@ -18967,7 +18986,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
       com_die_arg.decl_id = DECL_UID (com_decl);
       com_die_arg.die_parent = context_die;
       com_die = (dw_die_ref) htab_find (common_block_die_table, &com_die_arg);
-      loc = loc_list_from_tree (com_decl, 2);
+      loc = loc_list_from_tree (com_decl, 2, NULL);
       if (com_die == NULL)
 	{
 	  const char *cnam
@@ -18981,7 +19000,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
 	      add_AT_location_description (com_die, DW_AT_location, loc);
 	      /* Avoid sharing the same loc descriptor between
 		 DW_TAG_common_block and DW_TAG_variable.  */
-	      loc = loc_list_from_tree (com_decl, 2);
+	      loc = loc_list_from_tree (com_decl, 2, NULL);
 	    }
           else if (DECL_EXTERNAL (decl))
 	    add_AT_flag (com_die, DW_AT_declaration, 1);
@@ -18994,7 +19013,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
       else if (get_AT (com_die, DW_AT_location) == NULL && loc)
 	{
 	  add_AT_location_description (com_die, DW_AT_location, loc);
-	  loc = loc_list_from_tree (com_decl, 2);
+	  loc = loc_list_from_tree (com_decl, 2, NULL);
 	  remove_AT (com_die, DW_AT_declaration);
 	}
       var_die = new_die (DW_TAG_variable, com_die, decl);
-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PING] Enhance array types debug info. for Ada
  2014-10-08 19:05       ` Pierre-Marie de Rodat
@ 2014-10-22  8:55         ` Pierre-Marie de Rodat
  2014-11-05 16:37           ` [PING 2] " Pierre-Marie de Rodat
  2014-11-26 18:07         ` [PATCH] " Jakub Jelinek
  1 sibling, 1 reply; 20+ messages in thread
From: Pierre-Marie de Rodat @ 2014-10-22  8:55 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: GCC Patches

Hello,

On 10/08/2014 09:05 PM, Pierre-Marie de Rodat wrote:
> The latest patches bootstrapped well and passed successfully the GCC
> testsuite on x86_64-pc-linux-gnu.

Ping for https://gcc.gnu.org/ml/gcc-patches/2014-10/msg00694.html

Thanks in advance for you feedback!

-- 
Pierre-Marie de Rodat

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PING 2] Enhance array types debug info. for Ada
  2014-10-22  8:55         ` [PING] " Pierre-Marie de Rodat
@ 2014-11-05 16:37           ` Pierre-Marie de Rodat
  2014-11-26 16:13             ` [PING 3] " Pierre-Marie de Rodat
  0 siblings, 1 reply; 20+ messages in thread
From: Pierre-Marie de Rodat @ 2014-11-05 16:37 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: GCC Patches

Hello,

Ping for https://gcc.gnu.org/ml/gcc-patches/2014-10/msg00694.html

Thanks in advance!
Regards,

-- 
Pierre-Marie de Rodat

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PING 3] Enhance array types debug info. for Ada
  2014-11-05 16:37           ` [PING 2] " Pierre-Marie de Rodat
@ 2014-11-26 16:13             ` Pierre-Marie de Rodat
  0 siblings, 0 replies; 20+ messages in thread
From: Pierre-Marie de Rodat @ 2014-11-26 16:13 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: GCC Patches

Hello,

Ping for https://gcc.gnu.org/ml/gcc-patches/2014-10/msg00694.html

Thanks in advance!
Regards,

-- 
Pierre-Marie de Rodat

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] Enhance array types debug info. for Ada
  2014-10-08 19:05       ` Pierre-Marie de Rodat
  2014-10-22  8:55         ` [PING] " Pierre-Marie de Rodat
@ 2014-11-26 18:07         ` Jakub Jelinek
  2014-12-01 15:29           ` Pierre-Marie de Rodat
  1 sibling, 1 reply; 20+ messages in thread
From: Jakub Jelinek @ 2014-11-26 18:07 UTC (permalink / raw)
  To: Pierre-Marie de Rodat; +Cc: GCC Patches

On Wed, Oct 08, 2014 at 09:05:30PM +0200, Pierre-Marie de Rodat wrote:
> gcc/
> 	* dwarf2out.h (struct array_descr_info): Remove the base_decl field.
> 	* dwarf2out.c (enum dw_scalar_form): New.
> 	(struct loc_descr_context): New.
> 	(add_scalar_info): New.
> 	(add_bound_info): Add a context parameter.  Use add_scalar_info.
> 	(loc_list_from_tree): Add a context parameter.  Handle PLACEHOLDER_EXPR
> 	nodes for type-related expressions.  Likewise for base declarations.
> 	(loc_descriptor_from_tree): Add a context parameter.
> 	(subrange_type_die): Update calls to add_bound_info.
> 	(tls_mem_loc_descriptor): Likewise.
> 	(loc_list_for_address_of_addr_expr_of_indirect_ref): Add a context
> 	parameter.  Update calls to loc_list_from_tree.
> 	(add_subscript_info): Update calls to add_bound_info.
> 	(gen_array_type_die): Update calls to loc_list_from_tree and to
> 	add_bound_info.
> 	(descr_info_loc): Remove.
> 	(add_descr_info_field): Remove.
> 	(gen_descr_array_type_die): Switch add_descr_info_field calls into
> 	add_scalar_info/add_bound_info ones.
> 	(gen_subprogram_die): Update calls to loc_list_from_tree.
> 	(gen_variable_die): Likewise.

Replace implicitely with implicitly in the whole patch.

> +     to refer to register values).
> +
> +   CONTEXT provides information to customize the location descriptions
> +   generation.  Its context_type field specifies what type is implicitely
> +   referenced by DW_OP_push_object_address.  If it is NULL_TREE, this operation
> +   will not be generated.
> +
> +   If CONTEXT is NULL, the behavior is the same as if the context_type field
> +   was NULL_TREE.  */

as if both context_type and base_decl were NULL_TREE?

> @@ -14311,6 +14351,12 @@ loc_list_from_tree (tree loc, int want_address)
>       extending the values properly.  Hopefully this won't be a real
>       problem...  */
>  
> +  if (context != NULL
> +      && context->base_decl == loc
> +      && want_address == 0)
> +    return new_loc_list (new_loc_descr (DW_OP_push_object_address, 0, 0),
> +			 NULL, NULL, NULL);
> +

This isn't guarded with dwarf_version >= 3 || !dwarf_strict.  Shouldn't it
be too and return NULL otherwise?

> +	expansion_failed (loc, NULL_RTX,
> +			  "PLACEHOLDER_EXPR for a unexpected type");

for an unexpected type?

> @@ -14533,7 +14594,8 @@ loc_list_from_tree (tree loc, int want_address)
>  
>  	list_ret = loc_list_from_tree (obj,
>  				       want_address == 2
> -				       && !bitpos && !offset ? 2 : 1);
> +				       && !bitpos && !offset ? 2 : 1,
> +                                       context);

Formatting.  Should use tabs, not spaces.

> +      if (prec <= HOST_BITS_PER_WIDE_INT
> +	       || tree_fits_uhwi_p (value))

Formatting.  || should be below p in prec.

Would be nice if you tried more than one fortran testcase, say build
all gfortran.dg/ tests with -O0 -g -dA (and perhaps -O2 -g -dA afterwards)
with both unpatched and patched compilers and diff *.s files?

Otherwise, LGTM.

	Jakub

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] Enhance array types debug info. for Ada
  2014-11-26 18:07         ` [PATCH] " Jakub Jelinek
@ 2014-12-01 15:29           ` Pierre-Marie de Rodat
  2014-12-01 15:37             ` Jakub Jelinek
  0 siblings, 1 reply; 20+ messages in thread
From: Pierre-Marie de Rodat @ 2014-12-01 15:29 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 2294 bytes --]

On 11/26/2014 06:42 PM, Jakub Jelinek wrote:
> Replace implicitely with implicitly in the whole patch.

Oops! Done.

>> +   If CONTEXT is NULL, the behavior is the same as if the context_type field
>> +   was NULL_TREE.  */
>
> as if both context_type and base_decl were NULL_TREE?

Absolutely: done.

>> +  if (context != NULL
>> +      && context->base_decl == loc
>> +      && want_address == 0)
>> +    return new_loc_list (new_loc_descr (DW_OP_push_object_address, 0, 0),
>> +			 NULL, NULL, NULL);
>> +
>
> This isn't guarded with dwarf_version >= 3 || !dwarf_strict.  Shouldn't it
> be too and return NULL otherwise?

Yes it should: I added this guard.

>> +	expansion_failed (loc, NULL_RTX,
>> +			  "PLACEHOLDER_EXPR for a unexpected type");
>
> for an unexpected type?

Yes: placeholder expressions are supposed only to refer to the type 
allowed by the context. I updated the message to talk about the context 
and I added another one for the (invalid) case when want_address == 0.

> Formatting.  Should use tabs, not spaces.
> [...]
> Formatting.  || should be below p in prec.

Fixed. Thank you for the review.

> Would be nice if you tried more than one fortran testcase, say build
> all gfortran.dg/ tests with -O0 -g -dA (and perhaps -O2 -g -dA afterwards)
> with both unpatched and patched compilers and diff *.s files?
>
> Otherwise, LGTM.

That was a very good idea: thanks to these diffs I realized that in 
add_scalar_info, a "return" statement got lost in the process of porting 
my patches to trunk. This caused duplication of scalar constant 
attributes in the output debugging information.

Beyond this, I checked diffs for -O0, -O1 and -O2 (each one with -g 
-dA). Trying to skip all the noise caused by the changes of DIE 
offsets/abbreviation numbers, the only significant changes I could find 
look legitimate:

   - Volatile array types used not to be described as such: after my 
patches they are wrapped in DW_TAG_volatile_type DIEs.

   - DW_AT_{lower,upper}_bound attributes are now encoded as 
DW_FORM_sdata (i.e. SLEB128) instead of as DW_FORM_data1/2/4/8. This is 
a clear win for negative ones.

I attached the only updated patch. The new patch set bootstrapped well 
and was successfully regtested on x86_64-linux.

Thank you,

-- 
Pierre-Marie de Rodat

[-- Attachment #2: gcc-0005-dwarf2out.c-do-not-short-circuit-add_bound_info-in-a.patch --]
[-- Type: text/x-diff, Size: 33517 bytes --]

From 4a8fe9204873864fd7ac898622d09a1d60bcea6b Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Mon, 9 Jun 2014 15:13:45 +0200
Subject: [PATCH 5/5] dwarf2out.c: do not short-circuit add_bound_info in
 array descr. lang-hook

gcc/
	* dwarf2out.h (struct array_descr_info): Remove the base_decl field.
	* dwarf2out.c (enum dw_scalar_form): New.
	(struct loc_descr_context): New.
	(add_scalar_info): New.
	(add_bound_info): Add a context parameter.  Use add_scalar_info.
	(loc_list_from_tree): Add a context parameter.  Handle PLACEHOLDER_EXPR
	nodes for type-related expressions.  Likewise for base declarations.
	(loc_descriptor_from_tree): Add a context parameter.
	(subrange_type_die): Update calls to add_bound_info.
	(tls_mem_loc_descriptor): Likewise.
	(loc_list_for_address_of_addr_expr_of_indirect_ref): Add a context
	parameter.  Update calls to loc_list_from_tree.
	(add_subscript_info): Update calls to add_bound_info.
	(gen_array_type_die): Update calls to loc_list_from_tree and to
	add_bound_info.
	(descr_info_loc): Remove.
	(add_descr_info_field): Remove.
	(gen_descr_array_type_die): Switch add_descr_info_field calls into
	add_scalar_info/add_bound_info ones.
	(gen_subprogram_die): Update calls to loc_list_from_tree.
	(gen_variable_die): Likewise.
---
 gcc/dwarf2out.c |  574 +++++++++++++++++++++++++++++--------------------------
 1 file changed, 299 insertions(+), 275 deletions(-)

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 4d6da4b..115eaa2 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -3029,6 +3029,15 @@ static bool frame_pointer_fb_offset_valid;
 
 static vec<dw_die_ref> base_types;
 
+/* Flags to represent a set of attribute classes for attributes that represent
+   a scalar value (bounds, pointers, ...).  */
+enum dw_scalar_form
+{
+  dw_scalar_form_constant = 0x01,
+  dw_scalar_form_exprloc = 0x02,
+  dw_scalar_form_reference = 0x04
+};
+
 /* Forward declarations for functions defined in this file.  */
 
 static int is_pseudo_reg (const_rtx);
@@ -3203,8 +3212,11 @@ static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx,
 					       enum var_init_status);
 static dw_loc_descr_ref loc_descriptor (rtx, machine_mode mode,
 					enum var_init_status);
-static dw_loc_list_ref loc_list_from_tree (tree, int);
-static dw_loc_descr_ref loc_descriptor_from_tree (tree, int);
+struct loc_descr_context;
+static dw_loc_list_ref loc_list_from_tree (tree, int,
+					   const struct loc_descr_context *);
+static dw_loc_descr_ref loc_descriptor_from_tree (tree, int,
+						  const struct loc_descr_context *);
 static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
 static tree field_type (const_tree);
 static unsigned int simple_type_align_in_bits (const_tree);
@@ -3226,7 +3238,10 @@ static bool tree_add_const_value_attribute_for_decl (dw_die_ref, tree);
 static void add_name_attribute (dw_die_ref, const char *);
 static void add_gnat_descriptive_type_attribute (dw_die_ref, tree, dw_die_ref);
 static void add_comp_dir_attribute (dw_die_ref);
-static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree);
+static void add_scalar_info (dw_die_ref, enum dwarf_attribute, tree, int,
+			     const struct loc_descr_context *);
+static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree,
+			    const struct loc_descr_context *);
 static void add_subscript_info (dw_die_ref, tree, bool);
 static void add_byte_size_attribute (dw_die_ref, tree);
 static void add_bit_offset_attribute (dw_die_ref, tree);
@@ -10556,9 +10571,9 @@ subrange_type_die (tree type, tree low, tree high, dw_die_ref context_die)
     }
 
   if (low)
-    add_bound_info (subrange_die, DW_AT_lower_bound, low);
+    add_bound_info (subrange_die, DW_AT_lower_bound, low, NULL);
   if (high)
-    add_bound_info (subrange_die, DW_AT_upper_bound, high);
+    add_bound_info (subrange_die, DW_AT_upper_bound, high, NULL);
 
   return subrange_die;
 }
@@ -11534,7 +11549,7 @@ tls_mem_loc_descriptor (rtx mem)
       || !DECL_THREAD_LOCAL_P (base))
     return NULL;
 
-  loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), 1);
+  loc_result = loc_descriptor_from_tree (MEM_EXPR (mem), 1, NULL);
   if (loc_result == NULL)
     return NULL;
 
@@ -14272,10 +14287,13 @@ cst_pool_loc_descr (tree loc)
 
 /* Return dw_loc_list representing address of addr_expr LOC
    by looking for inner INDIRECT_REF expression and turning
-   it into simple arithmetics.  */
+   it into simple arithmetics.
+
+   See loc_list_from_tree for the meaning of CONTEXT.  */
 
 static dw_loc_list_ref
-loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
+loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev,
+						   const loc_descr_context *context)
 {
   tree obj, offset;
   HOST_WIDE_INT bitsize, bitpos, bytepos;
@@ -14299,18 +14317,19 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
       return 0;
     }
   if (!offset && !bitpos)
-    list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), toplev ? 2 : 1);
+    list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), toplev ? 2 : 1,
+				   context);
   else if (toplev
 	   && int_size_in_bytes (TREE_TYPE (loc)) <= DWARF2_ADDR_SIZE
 	   && (dwarf_version >= 4 || !dwarf_strict))
     {
-      list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (obj, 0), 0, context);
       if (!list_ret)
 	return 0;
       if (offset)
 	{
 	  /* Variable offset.  */
-	  list_ret1 = loc_list_from_tree (offset, 0);
+	  list_ret1 = loc_list_from_tree (offset, 0, context);
 	  if (list_ret1 == 0)
 	    return 0;
 	  add_loc_list (&list_ret, list_ret1);
@@ -14333,15 +14352,36 @@ loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev)
 }
 
 
+/* Helper structure for location descriptions generation.  */
+struct loc_descr_context
+{
+  /* The type that is implicitly referenced by DW_OP_push_object_address, or
+     NULL_TREE if DW_OP_push_object_address in invalid for this location
+     description.  This is used when processing PLACEHOLDER_EXPR nodes.  */
+  tree context_type;
+  /* The ..._DECL node that should be translated as a
+     DW_OP_push_object_address operation.  */
+  tree base_decl;
+};
+
 /* Generate Dwarf location list representing LOC.
    If WANT_ADDRESS is false, expression computing LOC will be computed
    If WANT_ADDRESS is 1, expression computing address of LOC will be returned
    if WANT_ADDRESS is 2, expression computing address useable in location
      will be returned (i.e. DW_OP_reg can be used
-     to refer to register values).  */
+     to refer to register values).
+
+   CONTEXT provides information to customize the location descriptions
+   generation.  Its context_type field specifies what type is implicitly
+   referenced by DW_OP_push_object_address.  If it is NULL_TREE, this operation
+   will not be generated.
+
+   If CONTEXT is NULL, the behavior is the same as if both context_type and
+   base_decl fields were NULL_TREE.  */
 
 static dw_loc_list_ref
-loc_list_from_tree (tree loc, int want_address)
+loc_list_from_tree (tree loc, int want_address,
+		    const struct loc_descr_context *context)
 {
   dw_loc_descr_ref ret = NULL, ret1 = NULL;
   dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
@@ -14352,6 +14392,17 @@ loc_list_from_tree (tree loc, int want_address)
      extending the values properly.  Hopefully this won't be a real
      problem...  */
 
+  if (context != NULL
+      && context->base_decl == loc
+      && want_address == 0)
+    {
+      if (dwarf_version >= 3 || !dwarf_strict)
+	return new_loc_list (new_loc_descr (DW_OP_push_object_address, 0, 0),
+			     NULL, NULL, NULL);
+      else
+	return NULL;
+    }
+
   switch (TREE_CODE (loc))
     {
     case ERROR_MARK:
@@ -14360,11 +14411,25 @@ loc_list_from_tree (tree loc, int want_address)
 
     case PLACEHOLDER_EXPR:
       /* This case involves extracting fields from an object to determine the
-	 position of other fields.  We don't try to encode this here.  The
-	 only user of this is Ada, which encodes the needed information using
-	 the names of types.  */
-      expansion_failed (loc, NULL_RTX, "PLACEHOLDER_EXPR");
-      return 0;
+	 position of other fields. It is supposed to appear only as the first
+	 operand of COMPONENT_REF nodes and to reference precisely the type
+	 that the context allows.  */
+      if (context == NULL || TREE_TYPE (loc) == context->context_type)
+	expansion_failed (loc, NULL_RTX,
+			  "PLACEHOLDER_EXPR in invalid context");
+      else if (want_address == 0)
+	expansion_failed (loc, NULL_RTX,
+			  "Want value of PLACEHOLDER_EXPR:"
+			  " only address is valid");
+      else if (dwarf_version >= 3 || !dwarf_strict)
+	{
+	  ret = new_loc_descr (DW_OP_push_object_address, 0, 0);
+	  have_address = 1;
+	  break;
+	}
+      else
+	return NULL;
+      break;
 
     case CALL_EXPR:
       expansion_failed (loc, NULL_RTX, "CALL_EXPR");
@@ -14385,7 +14450,7 @@ loc_list_from_tree (tree loc, int want_address)
       if (want_address)
 	{
 	  list_ret = loc_list_for_address_of_addr_expr_of_indirect_ref
-		       (loc, want_address == 2);
+		       (loc, want_address == 2, context);
 	  if (list_ret)
 	    have_address = 1;
 	  else if (decl_address_ip_invariant_p (TREE_OPERAND (loc, 0))
@@ -14394,7 +14459,7 @@ loc_list_from_tree (tree loc, int want_address)
 	}
         /* Otherwise, process the argument and look for the address.  */
       if (!list_ret && !ret)
-        list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 1);
+        list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 1, context);
       else
 	{
 	  if (want_address)
@@ -14464,7 +14529,7 @@ loc_list_from_tree (tree loc, int want_address)
     case RESULT_DECL:
       if (DECL_HAS_VALUE_EXPR_P (loc))
 	return loc_list_from_tree (DECL_VALUE_EXPR (loc),
-				   want_address);
+				   want_address, context);
       /* FALLTHRU */
 
     case FUNCTION_DECL:
@@ -14538,7 +14603,7 @@ loc_list_from_tree (tree loc, int want_address)
 	}
       /* Fallthru.  */
     case INDIRECT_REF:
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
       have_address = 1;
       break;
 
@@ -14547,13 +14612,13 @@ loc_list_from_tree (tree loc, int want_address)
       return NULL;
 
     case COMPOUND_EXPR:
-      return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address);
+      return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address, context);
 
     CASE_CONVERT:
     case VIEW_CONVERT_EXPR:
     case SAVE_EXPR:
     case MODIFY_EXPR:
-      return loc_list_from_tree (TREE_OPERAND (loc, 0), want_address);
+      return loc_list_from_tree (TREE_OPERAND (loc, 0), want_address, context);
 
     case COMPONENT_REF:
     case BIT_FIELD_REF:
@@ -14574,7 +14639,8 @@ loc_list_from_tree (tree loc, int want_address)
 
 	list_ret = loc_list_from_tree (obj,
 				       want_address == 2
-				       && !bitpos && !offset ? 2 : 1);
+				       && !bitpos && !offset ? 2 : 1,
+				       context);
 	/* TODO: We can extract value of the small expression via shifting even
 	   for nonzero bitpos.  */
 	if (list_ret == 0)
@@ -14589,7 +14655,7 @@ loc_list_from_tree (tree loc, int want_address)
 	if (offset != NULL_TREE)
 	  {
 	    /* Variable offset.  */
-	    list_ret1 = loc_list_from_tree (offset, 0);
+	    list_ret1 = loc_list_from_tree (offset, 0, context);
 	    if (list_ret1 == 0)
 	      return 0;
 	    add_loc_list (&list_ret, list_ret1);
@@ -14679,8 +14745,8 @@ loc_list_from_tree (tree loc, int want_address)
 	  op = DW_OP_mod;
 	  goto do_binop;
 	}
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
-      list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
+      list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0, context);
       if (list_ret == 0 || list_ret1 == 0)
 	return 0;
 
@@ -14711,7 +14777,7 @@ loc_list_from_tree (tree loc, int want_address)
     do_plus:
       if (tree_fits_shwi_p (TREE_OPERAND (loc, 1)))
 	{
-	  list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+	  list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
 	  if (list_ret == 0)
 	    return 0;
 
@@ -14759,8 +14825,8 @@ loc_list_from_tree (tree loc, int want_address)
       goto do_binop;
 
     do_binop:
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
-      list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
+      list_ret1 = loc_list_from_tree (TREE_OPERAND (loc, 1), 0, context);
       if (list_ret == 0 || list_ret1 == 0)
 	return 0;
 
@@ -14784,7 +14850,7 @@ loc_list_from_tree (tree loc, int want_address)
       goto do_unop;
 
     do_unop:
-      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+      list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
       if (list_ret == 0)
 	return 0;
 
@@ -14808,12 +14874,12 @@ loc_list_from_tree (tree loc, int want_address)
     case COND_EXPR:
       {
 	dw_loc_descr_ref lhs
-	  = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0);
+	  = loc_descriptor_from_tree (TREE_OPERAND (loc, 1), 0, context);
 	dw_loc_list_ref rhs
-	  = loc_list_from_tree (TREE_OPERAND (loc, 2), 0);
+	  = loc_list_from_tree (TREE_OPERAND (loc, 2), 0, context);
 	dw_loc_descr_ref bra_node, jump_node, tmp;
 
-	list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0);
+	list_ret = loc_list_from_tree (TREE_OPERAND (loc, 0), 0, context);
 	if (list_ret == 0 || lhs == 0 || rhs == 0)
 	  return 0;
 
@@ -14919,9 +14985,10 @@ loc_list_from_tree (tree loc, int want_address)
 
 /* Same as above but return only single location expression.  */
 static dw_loc_descr_ref
-loc_descriptor_from_tree (tree loc, int want_address)
+loc_descriptor_from_tree (tree loc, int want_address,
+			  const struct loc_descr_context *context)
 {
-  dw_loc_list_ref ret = loc_list_from_tree (loc, want_address);
+  dw_loc_list_ref ret = loc_list_from_tree (loc, want_address, context);
   if (!ret)
     return NULL;
   if (ret->dw_loc_next)
@@ -15979,7 +16046,8 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
     }
   if (list == NULL)
     {
-      list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2);
+      list = loc_list_from_tree (decl, decl_by_reference_p (decl) ? 0 : 2,
+				 NULL);
       /* It is usually worth caching this result if the decl is from
 	 BLOCK_NONLOCALIZED_VARS and if the list has at least two elements.  */
       if (cache_p && list && list->dw_loc_next)
@@ -16473,6 +16541,143 @@ add_comp_dir_attribute (dw_die_ref die)
     add_AT_string (die, DW_AT_comp_dir, wd);
 }
 
+/* Given a tree node VALUE describing a scalar attribute ATTR (i.e. a bound, a
+   pointer computation, ...), output a representation for that bound according
+   to the accepted FORMS (see enum dw_scalar_form) and add it to DIE.  See
+   loc_list_from_tree for the meaning of CONTEXT.  */
+
+static void
+add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
+		 int forms, const struct loc_descr_context *context)
+{
+  dw_die_ref ctx, decl_die;
+  dw_loc_list_ref list;
+
+  bool strip_conversions = true;
+
+  while (strip_conversions)
+    switch (TREE_CODE (value))
+      {
+      case ERROR_MARK:
+      case SAVE_EXPR:
+	return;
+
+      CASE_CONVERT:
+      case VIEW_CONVERT_EXPR:
+	value = TREE_OPERAND (value, 0);
+	break;
+
+      default:
+	strip_conversions = false;
+	break;
+      }
+
+  /* If possible and permitted, output the attribute as a constant.  */
+  if ((forms & dw_scalar_form_constant) != 0
+      && TREE_CODE (value) == INTEGER_CST)
+    {
+      unsigned int prec = simple_type_size_in_bits (TREE_TYPE (value));
+
+      /* If HOST_WIDE_INT is big enough then represent the bound as
+	 a constant value.  We need to choose a form based on
+	 whether the type is signed or unsigned.  We cannot just
+	 call add_AT_unsigned if the value itself is positive
+	 (add_AT_unsigned might add the unsigned value encoded as
+	 DW_FORM_data[1248]).  Some DWARF consumers will lookup the
+	 bounds type and then sign extend any unsigned values found
+	 for signed types.  This is needed only for
+	 DW_AT_{lower,upper}_bound, since for most other attributes,
+	 consumers will treat DW_FORM_data[1248] as unsigned values,
+	 regardless of the underlying type.  */
+      if (prec <= HOST_BITS_PER_WIDE_INT
+	  || tree_fits_uhwi_p (value))
+	{
+	  if (TYPE_UNSIGNED (TREE_TYPE (value)))
+	    add_AT_unsigned (die, attr, TREE_INT_CST_LOW (value));
+	  else
+	    add_AT_int (die, attr, TREE_INT_CST_LOW (value));
+	}
+      else
+	/* Otherwise represent the bound as an unsigned value with
+	   the precision of its type.  The precision and signedness
+	   of the type will be necessary to re-interpret it
+	   unambiguously.  */
+	add_AT_wide (die, attr, value);
+      return;
+    }
+
+  /* Otherwise, if it's possible and permitted too, output a reference to
+     another DIE.  */
+  if ((forms & dw_scalar_form_reference) != 0)
+    {
+      tree decl = NULL_TREE;
+
+      /* Some type attributes reference an outer type.  For instance, the upper
+	 bound of an array may reference an embedding record (this happens in
+	 Ada).  */
+      if (TREE_CODE (value) == COMPONENT_REF
+	  && TREE_CODE (TREE_OPERAND (value, 0)) == PLACEHOLDER_EXPR
+	  && TREE_CODE (TREE_OPERAND (value, 1)) == FIELD_DECL)
+	decl = TREE_OPERAND (value, 1);
+
+      else if (TREE_CODE (value) == VAR_DECL
+	       || TREE_CODE (value) == PARM_DECL
+	       || TREE_CODE (value) == RESULT_DECL)
+	decl = value;
+
+      if (decl != NULL_TREE)
+	{
+	  dw_die_ref decl_die = lookup_decl_die (decl);
+
+	  /* ??? Can this happen, or should the variable have been bound
+	     first?  Probably it can, since I imagine that we try to create
+	     the types of parameters in the order in which they exist in
+	     the list, and won't have created a forward reference to a
+	     later parameter.  */
+	  if (decl_die != NULL)
+	    {
+	      add_AT_die_ref (die, attr, decl_die);
+	      return;
+	    }
+	}
+    }
+
+  /* Last chance: try to create a stack operation procedure to evaluate the
+     value.  Do nothing if even that is not possible or permitted.  */
+  if ((forms & dw_scalar_form_exprloc) == 0)
+    return;
+
+  list = loc_list_from_tree (value, 2, context);
+  if (list == NULL || single_element_loc_list_p (list))
+    {
+      /* If this attribute is not a reference nor constant, it is
+	 a DWARF expression rather than location description.  For that
+	 loc_list_from_tree (value, 0, &context) is needed.  */
+      dw_loc_list_ref list2 = loc_list_from_tree (value, 0, context);
+      if (list2 && single_element_loc_list_p (list2))
+	{
+	  add_AT_loc (die, attr, list2->expr);
+	  return;
+	}
+    }
+
+  /* If that failed to give a single element location list, fall back to
+     outputting this as a reference... still if permitted.  */
+  if (list == NULL || (forms & dw_scalar_form_reference) == 0)
+    return;
+
+  if (current_function_decl == 0)
+    ctx = comp_unit_die ();
+  else
+    ctx = lookup_decl_die (current_function_decl);
+
+  decl_die = new_die (DW_TAG_variable, ctx, value);
+  add_AT_flag (decl_die, DW_AT_artificial, 1);
+  add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, ctx);
+  add_AT_location_description (decl_die, DW_AT_location, list);
+  add_AT_die_ref (die, attr, decl_die);
+}
+
 /* Return the default for DW_AT_lower_bound, or -1 if there is not any
    default.  */
 
@@ -16517,121 +16722,41 @@ lower_bound_default (void)
    a representation for that bound.  */
 
 static void
-add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree bound)
+add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr,
+		tree bound, const struct loc_descr_context *context)
 {
-  switch (TREE_CODE (bound))
-    {
-    case ERROR_MARK:
-      return;
+  int dflt;
 
-    /* All fixed-bounds are represented by INTEGER_CST nodes.  */
-    case INTEGER_CST:
+  while (1)
+    switch (TREE_CODE (bound))
       {
-	unsigned int prec = simple_type_size_in_bits (TREE_TYPE (bound));
-	int dflt;
+      /* Strip all conversions.  */
+      CASE_CONVERT:
+      case VIEW_CONVERT_EXPR:
+	bound = TREE_OPERAND (bound, 0);
+	break;
 
-	/* Use the default if possible.  */
+      /* All fixed-bounds are represented by INTEGER_CST nodes.  Lower bounds
+	 are even omitted when they are the default.  */
+      case INTEGER_CST:
+	/* If the value for this bound is the default one, we can even omit the
+	   attribute.  */
 	if (bound_attr == DW_AT_lower_bound
 	    && tree_fits_shwi_p (bound)
 	    && (dflt = lower_bound_default ()) != -1
 	    && tree_to_shwi (bound) == dflt)
-	  ;
-
-	/* If HOST_WIDE_INT is big enough then represent the bound as
-	   a constant value.  We need to choose a form based on
-	   whether the type is signed or unsigned.  We cannot just
-	   call add_AT_unsigned if the value itself is positive
-	   (add_AT_unsigned might add the unsigned value encoded as
-	   DW_FORM_data[1248]).  Some DWARF consumers will lookup the
-	   bounds type and then sign extend any unsigned values found
-	   for signed types.  This is needed only for
-	   DW_AT_{lower,upper}_bound, since for most other attributes,
-	   consumers will treat DW_FORM_data[1248] as unsigned values,
-	   regardless of the underlying type.  */
-	else if (prec <= HOST_BITS_PER_WIDE_INT
-		 || tree_fits_uhwi_p (bound))
-	  {
-	    if (TYPE_UNSIGNED (TREE_TYPE (bound)))
-	      add_AT_unsigned (subrange_die, bound_attr,
-			       TREE_INT_CST_LOW (bound));
-	    else
-	      add_AT_int (subrange_die, bound_attr, TREE_INT_CST_LOW (bound));
-	  }
-	else
-	  /* Otherwise represent the bound as an unsigned value with
-	     the precision of its type.  The precision and signedness
-	     of the type will be necessary to re-interpret it
-	     unambiguously.  */
-	  add_AT_wide (subrange_die, bound_attr, bound);
-      }
-      break;
-
-    CASE_CONVERT:
-    case VIEW_CONVERT_EXPR:
-      add_bound_info (subrange_die, bound_attr, TREE_OPERAND (bound, 0));
-      break;
-
-    case SAVE_EXPR:
-      break;
-
-    case VAR_DECL:
-    case PARM_DECL:
-    case RESULT_DECL:
-      {
-	dw_die_ref decl_die = lookup_decl_die (bound);
-
-	/* ??? Can this happen, or should the variable have been bound
-	   first?  Probably it can, since I imagine that we try to create
-	   the types of parameters in the order in which they exist in
-	   the list, and won't have created a forward reference to a
-	   later parameter.  */
-	if (decl_die != NULL)
-	  {
-	    add_AT_die_ref (subrange_die, bound_attr, decl_die);
-	    break;
-	  }
-      }
-      /* FALLTHRU */
-
-    default:
-      {
-	/* Otherwise try to create a stack operation procedure to
-	   evaluate the value of the array bound.  */
-
-	dw_die_ref ctx, decl_die;
-	dw_loc_list_ref list;
-
-	list = loc_list_from_tree (bound, 2);
-	if (list == NULL || single_element_loc_list_p (list))
-	  {
-	    /* If DW_AT_*bound is not a reference nor constant, it is
-	       a DWARF expression rather than location description.
-	       For that loc_list_from_tree (bound, 0) is needed.
-	       If that fails to give a single element list,
-	       fall back to outputting this as a reference anyway.  */
-	    dw_loc_list_ref list2 = loc_list_from_tree (bound, 0);
-	    if (list2 && single_element_loc_list_p (list2))
-	      {
-		add_AT_loc (subrange_die, bound_attr, list2->expr);
-		break;
-	      }
-	  }
-	if (list == NULL)
-	  break;
+	  return;
 
-	if (current_function_decl == 0)
-	  ctx = comp_unit_die ();
-	else
-	  ctx = lookup_decl_die (current_function_decl);
+	/* FALLTHRU */
 
-	decl_die = new_die (DW_TAG_variable, ctx, bound);
-	add_AT_flag (decl_die, DW_AT_artificial, 1);
-	add_type_attribute (decl_die, TREE_TYPE (bound), TYPE_QUAL_CONST, ctx);
-	add_AT_location_description (decl_die, DW_AT_location, list);
-	add_AT_die_ref (subrange_die, bound_attr, decl_die);
-	break;
+      default:
+	add_scalar_info (subrange_die, bound_attr, bound,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference,
+			 context);
+	return;
       }
-    }
 }
 
 /* Add subscript info to TYPE_DIE, describing an array TYPE, collapsing
@@ -16688,9 +16813,9 @@ add_subscript_info (dw_die_ref type_die, tree type, bool collapse_p)
 	     to produce useful results, go ahead and output the lower
 	     bound solo, and hope the debugger can cope.  */
 
-	  add_bound_info (subrange_die, DW_AT_lower_bound, lower);
+	  add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL);
 	  if (upper)
-	    add_bound_info (subrange_die, DW_AT_upper_bound, upper);
+	    add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL);
 	}
 
       /* Otherwise we have an array type with an unspecified length.  The
@@ -17359,7 +17484,7 @@ gen_array_type_die (tree type, dw_die_ref context_die)
 	       && DECL_P (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
 	{
 	  tree szdecl = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
-	  dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2);
+	  dw_loc_list_ref loc = loc_list_from_tree (szdecl, 2, NULL);
 
 	  size = int_size_in_bytes (TREE_TYPE (szdecl));
 	  if (loc && size > 0)
@@ -17401,9 +17526,9 @@ gen_array_type_die (tree type, dw_die_ref context_die)
     {
       /* For VECTOR_TYPEs we use an array die with appropriate bounds.  */
       dw_die_ref subrange_die = new_die (DW_TAG_subrange_type, array_die, NULL);
-      add_bound_info (subrange_die, DW_AT_lower_bound, size_zero_node);
+      add_bound_info (subrange_die, DW_AT_lower_bound, size_zero_node, NULL);
       add_bound_info (subrange_die, DW_AT_upper_bound,
-		      size_int (TYPE_VECTOR_SUBPARTS (type) - 1));
+		      size_int (TYPE_VECTOR_SUBPARTS (type) - 1), NULL);
     }
   else
     add_subscript_info (array_die, type, collapse_nested_arrays);
@@ -17429,99 +17554,6 @@ gen_array_type_die (tree type, dw_die_ref context_die)
     add_pubtype (type, array_die);
 }
 
-static dw_loc_descr_ref
-descr_info_loc (tree val, tree base_decl)
-{
-  HOST_WIDE_INT size;
-  dw_loc_descr_ref loc, loc2;
-  enum dwarf_location_atom op;
-
-  if (val == base_decl)
-    return new_loc_descr (DW_OP_push_object_address, 0, 0);
-
-  switch (TREE_CODE (val))
-    {
-    CASE_CONVERT:
-      return descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-    case VAR_DECL:
-      return loc_descriptor_from_tree (val, 0);
-    case INTEGER_CST:
-      if (tree_fits_shwi_p (val))
-	return int_loc_descriptor (tree_to_shwi (val));
-      break;
-    case INDIRECT_REF:
-      size = int_size_in_bytes (TREE_TYPE (val));
-      if (size < 0)
-	break;
-      loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-      if (!loc)
-	break;
-      if (size == DWARF2_ADDR_SIZE)
-	add_loc_descr (&loc, new_loc_descr (DW_OP_deref, 0, 0));
-      else
-	add_loc_descr (&loc, new_loc_descr (DW_OP_deref_size, size, 0));
-      return loc;
-    case POINTER_PLUS_EXPR:
-    case PLUS_EXPR:
-      if (tree_fits_uhwi_p (TREE_OPERAND (val, 1))
-	  && tree_to_uhwi (TREE_OPERAND (val, 1)) < 16384)
-	{
-	  loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-	  if (!loc)
-	    break;
-	  loc_descr_plus_const (&loc, tree_to_shwi (TREE_OPERAND (val, 1)));
-	}
-      else
-	{
-	  op = DW_OP_plus;
-	do_binop:
-	  loc = descr_info_loc (TREE_OPERAND (val, 0), base_decl);
-	  if (!loc)
-	    break;
-	  loc2 = descr_info_loc (TREE_OPERAND (val, 1), base_decl);
-	  if (!loc2)
-	    break;
-	  add_loc_descr (&loc, loc2);
-	  add_loc_descr (&loc2, new_loc_descr (op, 0, 0));
-	}
-      return loc;
-    case MINUS_EXPR:
-      op = DW_OP_minus;
-      goto do_binop;
-    case MULT_EXPR:
-      op = DW_OP_mul;
-      goto do_binop;
-    case EQ_EXPR:
-      op = DW_OP_eq;
-      goto do_binop;
-    case NE_EXPR:
-      op = DW_OP_ne;
-      goto do_binop;
-    default:
-      break;
-    }
-  return NULL;
-}
-
-static void
-add_descr_info_field (dw_die_ref die, enum dwarf_attribute attr,
-		      tree val, tree base_decl)
-{
-  dw_loc_descr_ref loc;
-
-  if (tree_fits_shwi_p (val))
-    {
-      add_AT_unsigned (die, attr, tree_to_shwi (val));
-      return;
-    }
-
-  loc = descr_info_loc (val, base_decl);
-  if (!loc)
-    return;
-
-  add_AT_loc (die, attr, loc);
-}
-
 /* This routine generates DIE for array with hidden descriptor, details
    are filled into *info by a langhook.  */
 
@@ -17531,6 +17563,7 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 {
   const dw_die_ref scope_die = scope_die_for (type, context_die);
   const dw_die_ref array_die = new_die (DW_TAG_array_type, scope_die, type);
+  const struct loc_descr_context context = { type, info->base_decl };
   int dim;
 
   add_name_attribute (array_die, type_tag (type));
@@ -17552,15 +17585,18 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
   if (dwarf_version >= 3 || !dwarf_strict)
     {
       if (info->data_location)
-	add_descr_info_field (array_die, DW_AT_data_location,
-			      info->data_location,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_data_location, info->data_location,
+			 dw_scalar_form_exprloc, &context);
       if (info->associated)
-	add_descr_info_field (array_die, DW_AT_associated, info->associated,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_associated, info->associated,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference, &context);
       if (info->allocated)
-	add_descr_info_field (array_die, DW_AT_allocated, info->allocated,
-			      info->base_decl);
+	add_scalar_info (array_die, DW_AT_allocated, info->allocated,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference, &context);
     }
 
   add_gnat_descriptive_type_attribute (array_die, type, context_die);
@@ -17575,30 +17611,18 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
 			    info->dimen[dim].bounds_type, 0,
 			    context_die);
       if (info->dimen[dim].lower_bound)
-	{
-	  /* If it is the default value, omit it.  */
-	  int dflt;
-
-	  if (tree_fits_shwi_p (info->dimen[dim].lower_bound)
-	      && (dflt = lower_bound_default ()) != -1
-	      && tree_to_shwi (info->dimen[dim].lower_bound) == dflt)
-	    ;
-	  else
-	    add_descr_info_field (subrange_die, DW_AT_lower_bound,
-				  info->dimen[dim].lower_bound,
-				  info->base_decl);
-	}
+	add_bound_info (subrange_die, DW_AT_lower_bound,
+			info->dimen[dim].lower_bound, &context);
       if (info->dimen[dim].upper_bound)
-	add_descr_info_field (subrange_die, DW_AT_upper_bound,
-			      info->dimen[dim].upper_bound,
-			      info->base_decl);
-      if (dwarf_version >= 3 || !dwarf_strict)
-	{
-	  if (info->dimen[dim].stride)
-	    add_descr_info_field (subrange_die, DW_AT_byte_stride,
-				  info->dimen[dim].stride,
-				  info->base_decl);
-	}
+	add_bound_info (subrange_die, DW_AT_upper_bound,
+			info->dimen[dim].upper_bound, &context);
+      if ((dwarf_version >= 3 || !dwarf_strict) && info->dimen[dim].stride)
+	add_scalar_info (subrange_die, DW_AT_byte_stride,
+			 info->dimen[dim].stride,
+			 dw_scalar_form_constant
+			 | dw_scalar_form_exprloc
+			 | dw_scalar_form_reference,
+			 &context);
     }
 
   gen_type_die (info->element_type, context_die);
@@ -18662,7 +18686,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 
       if (fun->static_chain_decl)
 	add_AT_location_description (subr_die, DW_AT_static_link,
-		 loc_list_from_tree (fun->static_chain_decl, 2));
+		 loc_list_from_tree (fun->static_chain_decl, 2, NULL));
     }
 
   /* Generate child dies for template paramaters.  */
@@ -18991,7 +19015,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
 	{
 	  if (get_AT (var_die, DW_AT_location) == NULL)
 	    {
-	      loc = loc_list_from_tree (com_decl, off ? 1 : 2);
+	      loc = loc_list_from_tree (com_decl, off ? 1 : 2, NULL);
 	      if (loc)
 		{
 		  if (off)
@@ -19023,7 +19047,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
       com_die_arg.decl_id = DECL_UID (com_decl);
       com_die_arg.die_parent = context_die;
       com_die = common_block_die_table->find (&com_die_arg);
-      loc = loc_list_from_tree (com_decl, 2);
+      loc = loc_list_from_tree (com_decl, 2, NULL);
       if (com_die == NULL)
 	{
 	  const char *cnam
@@ -19037,7 +19061,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
 	      add_AT_location_description (com_die, DW_AT_location, loc);
 	      /* Avoid sharing the same loc descriptor between
 		 DW_TAG_common_block and DW_TAG_variable.  */
-	      loc = loc_list_from_tree (com_decl, 2);
+	      loc = loc_list_from_tree (com_decl, 2, NULL);
 	    }
           else if (DECL_EXTERNAL (decl))
 	    add_AT_flag (com_die, DW_AT_declaration, 1);
@@ -19050,7 +19074,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
       else if (get_AT (com_die, DW_AT_location) == NULL && loc)
 	{
 	  add_AT_location_description (com_die, DW_AT_location, loc);
-	  loc = loc_list_from_tree (com_decl, 2);
+	  loc = loc_list_from_tree (com_decl, 2, NULL);
 	  remove_AT (com_die, DW_AT_declaration);
 	}
       var_die = new_die (DW_TAG_variable, com_die, decl);
-- 
1.7.10.4


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] Enhance array types debug info. for Ada
  2014-12-01 15:29           ` Pierre-Marie de Rodat
@ 2014-12-01 15:37             ` Jakub Jelinek
  2014-12-01 16:41               ` Pierre-Marie de Rodat
  0 siblings, 1 reply; 20+ messages in thread
From: Jakub Jelinek @ 2014-12-01 15:37 UTC (permalink / raw)
  To: Pierre-Marie de Rodat; +Cc: GCC Patches

On Mon, Dec 01, 2014 at 04:29:05PM +0100, Pierre-Marie de Rodat wrote:
> >>+	expansion_failed (loc, NULL_RTX,
> >>+			  "PLACEHOLDER_EXPR for a unexpected type");
> >
> >for an unexpected type?
> 
> Yes: placeholder expressions are supposed only to refer to the type allowed
> by the context. I updated the message to talk about the context and I added
> another one for the (invalid) case when want_address == 0.

I meant that you wrote "a" rather than "an".

> Beyond this, I checked diffs for -O0, -O1 and -O2 (each one with -g -dA).
> Trying to skip all the noise caused by the changes of DIE
> offsets/abbreviation numbers, the only significant changes I could find look
> legitimate:
> 
>   - Volatile array types used not to be described as such: after my patches
> they are wrapped in DW_TAG_volatile_type DIEs.

Guess that is ok.

>   - DW_AT_{lower,upper}_bound attributes are now encoded as DW_FORM_sdata
> (i.e. SLEB128) instead of as DW_FORM_data1/2/4/8. This is a clear win for
> negative ones.

That might be a compatibility issue for older debuggers, especially for the
strict dwarf cases.  Where does this difference come from?  Why doesn't

> +      /* If HOST_WIDE_INT is big enough then represent the bound as
> +	 a constant value.  We need to choose a form based on
> +	 whether the type is signed or unsigned.  We cannot just
> +	 call add_AT_unsigned if the value itself is positive
> +	 (add_AT_unsigned might add the unsigned value encoded as
> +	 DW_FORM_data[1248]).  Some DWARF consumers will lookup the
> +	 bounds type and then sign extend any unsigned values found
> +	 for signed types.  This is needed only for
> +	 DW_AT_{lower,upper}_bound, since for most other attributes,
> +	 consumers will treat DW_FORM_data[1248] as unsigned values,
> +	 regardless of the underlying type.  */
> +      if (prec <= HOST_BITS_PER_WIDE_INT
> +	  || tree_fits_uhwi_p (value))
> +	{
> +	  if (TYPE_UNSIGNED (TREE_TYPE (value)))
> +	    add_AT_unsigned (die, attr, TREE_INT_CST_LOW (value));
> +	  else
> +	    add_AT_int (die, attr, TREE_INT_CST_LOW (value));
> +	}
> +      else
> +	/* Otherwise represent the bound as an unsigned value with
> +	   the precision of its type.  The precision and signedness
> +	   of the type will be necessary to re-interpret it
> +	   unambiguously.  */
> +	add_AT_wide (die, attr, value);

handle it the same as it used to?  Unconditional DW_FORM_sdata is certainly
not a size win for various values...

	Jakub

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH] Enhance array types debug info. for Ada
  2014-12-01 15:37             ` Jakub Jelinek
@ 2014-12-01 16:41               ` Pierre-Marie de Rodat
  2014-12-15 16:24                 ` [PING] " Pierre-Marie de Rodat
  0 siblings, 1 reply; 20+ messages in thread
From: Pierre-Marie de Rodat @ 2014-12-01 16:41 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: GCC Patches

On 12/01/2014 04:37 PM, Jakub Jelinek wrote:
>>> for an unexpected type?
>>
>> Yes: placeholder expressions are supposed only to refer to the type allowed
>> by the context. I updated the message to talk about the context and I added
>> another one for the (invalid) case when want_address == 0.
>
> I meant that you wrote "a" rather than "an".

Argh, sorry! ;-) Back to the simple and fixed version.

>>    - DW_AT_{lower,upper}_bound attributes are now encoded as DW_FORM_sdata
>> (i.e. SLEB128) instead of as DW_FORM_data1/2/4/8. This is a clear win for
>> negative ones.
>
> That might be a compatibility issue for older debuggers, especially for the
> strict dwarf cases.  Where does this difference come from?  Why doesn't
> [...]
>> +	    add_AT_unsigned (die, attr, TREE_INT_CST_LOW (value));
>> +	  else
>> +	    add_AT_int (die, attr, TREE_INT_CST_LOW (value));
> [...]
> handle it the same as it used to?  Unconditional DW_FORM_sdata is certainly
> not a size win for various values...

No, indeed: there are few positive values for which DW_FORM_sdata is one 
byte longer than the shortest appropriate DW_FORM_data1/2/4/8. However 
having different forms for the same attribute will generate as many 
abbreviations. I'm not sure how to balance what is best...

Besides if I understand correctly, the behavior of the code above has 
not changed. Instead, the array language hook used to call 
add_descr_info_field which itself used to call add_AT_unsigned even for 
signed types (instead of add_AT_int as above). Looking at add_AT_int and 
size_of_die, it looks like signed types are always encoded in SLEB128 in 
the "regular circuitry".

While I agree this might trigger compatibility issues with old 
debuggers, I don't know what to do assuming this change is not 
acceptable: should we add a kludge in add_scalar_info in order to force 
unsignedness when generating debugging information for Fortran?
-- 
Pierre-Marie de Rodat

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PING] Enhance array types debug info. for Ada
  2014-12-15 16:24                 ` [PING] " Pierre-Marie de Rodat
@ 2014-12-15 16:24                   ` Jakub Jelinek
  2014-12-17 16:36                     ` Pierre-Marie de Rodat
  0 siblings, 1 reply; 20+ messages in thread
From: Jakub Jelinek @ 2014-12-15 16:24 UTC (permalink / raw)
  To: Pierre-Marie de Rodat; +Cc: GCC Patches

On Mon, Dec 15, 2014 at 05:21:07PM +0100, Pierre-Marie de Rodat wrote:
> Ping for https://gcc.gnu.org/ml/gcc-patches/2014-12/msg00058.html.

Ok for trunk then.

> On 12/01/2014 05:40 PM, Pierre-Marie de Rodat wrote:
> >While I agree this might trigger compatibility issues with old
> >debuggers, I don't know what to do assuming this change is not
> >acceptable: should we add a kludge in add_scalar_info in order to force
> >unsignedness when generating debugging information for Fortran?
> 
> Here is a data point: I tried to debug gfortran.dg/array_function_2.f90
> build with my patches compiler for x86_64-linux with a GDB from an old GNAT
> Pro release (5.03a1, from 2005):
> 
> (gdb) b array_function_2.f90:24
> (gdb) r
> (gdb) ptype q_in
> type = real*8 (0:-1,-6:-1)
> 
> With a recent GDB, I have instead:
> (gdb) ptype q_in
> type = real(kind=8) (0:*,-6:*)
> 
> Given that the only thing that my patches changed in the debug information
> for this example is the encoding of the arrays' lower bounds, everything
> looks fine, here.
> 
> -- 
> Pierre-Marie de Rodat

	Jakub

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PING] Enhance array types debug info. for Ada
  2014-12-01 16:41               ` Pierre-Marie de Rodat
@ 2014-12-15 16:24                 ` Pierre-Marie de Rodat
  2014-12-15 16:24                   ` Jakub Jelinek
  0 siblings, 1 reply; 20+ messages in thread
From: Pierre-Marie de Rodat @ 2014-12-15 16:24 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: GCC Patches

Ping for https://gcc.gnu.org/ml/gcc-patches/2014-12/msg00058.html.

On 12/01/2014 05:40 PM, Pierre-Marie de Rodat wrote:
> While I agree this might trigger compatibility issues with old
> debuggers, I don't know what to do assuming this change is not
> acceptable: should we add a kludge in add_scalar_info in order to force
> unsignedness when generating debugging information for Fortran?

Here is a data point: I tried to debug gfortran.dg/array_function_2.f90 
build with my patches compiler for x86_64-linux with a GDB from an old 
GNAT Pro release (5.03a1, from 2005):

(gdb) b array_function_2.f90:24
(gdb) r
(gdb) ptype q_in
type = real*8 (0:-1,-6:-1)

With a recent GDB, I have instead:
(gdb) ptype q_in
type = real(kind=8) (0:*,-6:*)

Given that the only thing that my patches changed in the debug 
information for this example is the encoding of the arrays' lower 
bounds, everything looks fine, here.

-- 
Pierre-Marie de Rodat

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PING] Enhance array types debug info. for Ada
  2014-12-15 16:24                   ` Jakub Jelinek
@ 2014-12-17 16:36                     ` Pierre-Marie de Rodat
  0 siblings, 0 replies; 20+ messages in thread
From: Pierre-Marie de Rodat @ 2014-12-17 16:36 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: GCC Patches

On 12/15/2014 05:24 PM, Jakub Jelinek wrote:
> Ok for trunk then.

All the 5 commits are submitted. Thank you very much for your review! :-)

-- 
Pierre-Marie de Rodat

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2014-12-17 16:28 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-03  8:36 [PATCH] Enhance array types debug info. for Ada Pierre-Marie de Rodat
2014-09-17 14:38 ` [PING] " Pierre-Marie de Rodat
2014-10-03  8:59   ` [PING 2] " Pierre-Marie de Rodat
2014-10-03 16:42   ` [PING] " Jason Merrill
2014-10-07  8:08     ` Pierre-Marie de Rodat
2014-10-03  9:19 ` [PATCH] " Jakub Jelinek
2014-10-03  9:20   ` Jakub Jelinek
2014-10-07  8:08   ` Pierre-Marie de Rodat
2014-10-07  8:29     ` Jakub Jelinek
2014-10-08 19:05       ` Pierre-Marie de Rodat
2014-10-22  8:55         ` [PING] " Pierre-Marie de Rodat
2014-11-05 16:37           ` [PING 2] " Pierre-Marie de Rodat
2014-11-26 16:13             ` [PING 3] " Pierre-Marie de Rodat
2014-11-26 18:07         ` [PATCH] " Jakub Jelinek
2014-12-01 15:29           ` Pierre-Marie de Rodat
2014-12-01 15:37             ` Jakub Jelinek
2014-12-01 16:41               ` Pierre-Marie de Rodat
2014-12-15 16:24                 ` [PING] " Pierre-Marie de Rodat
2014-12-15 16:24                   ` Jakub Jelinek
2014-12-17 16:36                     ` Pierre-Marie de Rodat

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).