Generate debug info for local dynamic record types

Message ID 2787529.e9J7NaK4W3@fomalhaut
State New
Headers show
Series
  • Generate debug info for local dynamic record types
Related show

Commit Message

Eric Botcazou May 1, 2021, 5:55 p.m.
Hi,

in Ada you can embed VLAs in local record types and thus end up with dynamic
offsets in record types, which are currently not well described in DWARF
because 1) the temporaries generated for them by the gimplifier are naturally
DECL_IGNORED_P and 2) when the types are referenced in nested subprograms,
the DWARF back-end does not correctly handle the rewritten references.

The attached patch fixes 1) by reusing the trick already used for VLAs and
2) by deferring the resolution of these references to the late DWARF pass.

Tested on x86-64/Linux, both GCC and GDB, OK for the mainline?


2021-05-01  Eric Botcazou  <ebotcazou@adacore.com>

	* dwarf2out.c (loc_list_from_tree_1) <DECL>: During early DWARF, do not
	expand the VALUE_EXPR of variables put in the non-local frame.
	* gimplify.c (gimplify_type_sizes) <RECORD_TYPE>: If the type is not to
	be ignored for debug info, ensure its variable offsets are not either.

-- 
Eric Botcazou

Comments

David Malcolm via Gcc-patches May 4, 2021, 12:54 p.m. | #1
On Sat, May 1, 2021 at 9:04 PM Eric Botcazou <botcazou@adacore.com> wrote:
>

> Hi,

>

> in Ada you can embed VLAs in local record types and thus end up with dynamic

> offsets in record types, which are currently not well described in DWARF

> because 1) the temporaries generated for them by the gimplifier are naturally

> DECL_IGNORED_P and 2) when the types are referenced in nested subprograms,

> the DWARF back-end does not correctly handle the rewritten references.

>

> The attached patch fixes 1) by reusing the trick already used for VLAs and

> 2) by deferring the resolution of these references to the late DWARF pass.

>

> Tested on x86-64/Linux, both GCC and GDB, OK for the mainline?


OK.  I suppose there's no easy way to build a gnat.dg "guality"
testcase for this?

Thanks,
Richard.

>

> 2021-05-01  Eric Botcazou  <ebotcazou@adacore.com>

>

>         * dwarf2out.c (loc_list_from_tree_1) <DECL>: During early DWARF, do not

>         expand the VALUE_EXPR of variables put in the non-local frame.

>         * gimplify.c (gimplify_type_sizes) <RECORD_TYPE>: If the type is not to

>         be ignored for debug info, ensure its variable offsets are not either.

>

> --

> Eric Botcazou
Eric Botcazou May 5, 2021, 10:06 a.m. | #2
> OK.


Thanks.

> I suppose there's no easy way to build a gnat.dg "guality" testcase for

> this?


On all the platforms I test, I have a bunch of guality failures so I'm not 
really thrilled by the idea...  This should be covered by the GDB testsuite 
run with -fgnat-encodings=minimal but it's actually easy to check in DWARF 5.


	* gnat.dg/debug17.adb: New test.

-- 
Eric Botcazou
-- { dg-do compile }
-- { dg-skip-if "No Dwarf" { { hppa*-*-hpux* } && { ! lp64 } } }
-- { dg-options "-cargs -O0 -g -dA -fgnat-encodings=minimal -margs" }

pragma No_Component_Reordering;

procedure Debug17 (Number_Of_Bits : Natural) is

   type Bitinfos_T is array (Natural range 1 .. Number_Of_Bits) of Float;

   type Inner_Record_T is
      record
         Bitinfos : Bitinfos_T := (others => 1.5);
         Check1 : Integer := 1983;
         Check2 : Integer := 1995;
         Flag : Boolean := False;
         Check3 : Integer := 2005;

      end record;

   Rfield : Inner_Record_T;

begin
   null;
end;

-- { dg-final { scan-assembler-not "DW_AT_data_member_location (0)" } }

Patch

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index c36fd5a7f6a..5b819ab1a92 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -18658,8 +18658,20 @@  loc_list_from_tree_1 (tree loc, int want_address,
 
     case RESULT_DECL:
       if (DECL_HAS_VALUE_EXPR_P (loc))
-	return loc_list_from_tree_1 (DECL_VALUE_EXPR (loc),
-				     want_address, context);
+	{
+	  tree value_expr = DECL_VALUE_EXPR (loc);
+
+	  /* Non-local frame structures are DECL_IGNORED_P variables so we need
+	     to wait until they get an RTX in order to reference them.  */
+	  if (early_dwarf
+	      && TREE_CODE (value_expr) == COMPONENT_REF
+	      && VAR_P (TREE_OPERAND (value_expr, 0))
+	      && DECL_NONLOCAL_FRAME (TREE_OPERAND (value_expr, 0)))
+	    ;
+	  else
+	    return loc_list_from_tree_1 (value_expr, want_address, context);
+	}
+
       /* FALLTHRU */
 
     case FUNCTION_DECL:
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index b65106b1459..e790f08b23f 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -15141,11 +15141,15 @@  gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
 void
 gimplify_type_sizes (tree type, gimple_seq *list_p)
 {
-  tree field, t;
-
   if (type == NULL || type == error_mark_node)
     return;
 
+  const bool ignored_p
+    = TYPE_NAME (type)
+      && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+      && DECL_IGNORED_P (TYPE_NAME (type));
+  tree t;
+
   /* We first do the main variant, then copy into any other variants.  */
   type = TYPE_MAIN_VARIANT (type);
 
@@ -15179,9 +15183,7 @@  gimplify_type_sizes (tree type, gimple_seq *list_p)
       /* Ensure VLA bounds aren't removed, for -O0 they should be variables
 	 with assigned stack slots, for -O1+ -g they should be tracked
 	 by VTA.  */
-      if (!(TYPE_NAME (type)
-	    && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
-	    && DECL_IGNORED_P (TYPE_NAME (type)))
+      if (!ignored_p
 	  && TYPE_DOMAIN (type)
 	  && INTEGRAL_TYPE_P (TYPE_DOMAIN (type)))
 	{
@@ -15197,10 +15199,16 @@  gimplify_type_sizes (tree type, gimple_seq *list_p)
     case RECORD_TYPE:
     case UNION_TYPE:
     case QUAL_UNION_TYPE:
-      for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+      for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
 	if (TREE_CODE (field) == FIELD_DECL)
 	  {
 	    gimplify_one_sizepos (&DECL_FIELD_OFFSET (field), list_p);
+	    /* Likewise, ensure variable offsets aren't removed.  */
+	    if (!ignored_p
+		&& (t = DECL_FIELD_OFFSET (field))
+		&& VAR_P (t)
+		&& DECL_ARTIFICIAL (t))
+	      DECL_IGNORED_P (t) = 0;
 	    gimplify_one_sizepos (&DECL_SIZE (field), list_p);
 	    gimplify_one_sizepos (&DECL_SIZE_UNIT (field), list_p);
 	    gimplify_type_sizes (TREE_TYPE (field), list_p);