[PATCH] Fix debug info for COMMON and EQUIVALENCEd variables (regression from 3.4.x)

Jakub Jelinek jakub@redhat.com
Tue Oct 11 15:25:00 GMT 2005


Hi!

Say on:
      common /abc/ i, j, k
      i = 4
      j = 8
      k = 12
      write (unit=*, fmt='(i1i1i2)'), i, j, k
      end
or
      equivalence (i, j, k)
      i = 4
      write (unit=*, fmt='(i1)'), i
      end
or
      equivalence (i, j, k)
      save i, j, k
      i = 4
      write (unit=*, fmt='(i1)'), i
      end
gfortran doesn't output debug info for the used variables (i, j, k
in these testcases), while g77 emitted that just fine, so you could
inspect the variables in the debugger.

This patch sets the equivalenced or common variable backend_decl's
to a VAR_DECL instead of COMPONENT_REF, with
DECL_HAS_VALUE_EXPR (backend_decl) set to the COMPONENT_REF.
That is gimplified into the COMPONENT_REF, but the VAR_DECL is there
and passed to the debugger (and for OpenMP variable remapping as well).

The f95-lang.c part is a little bit ugly.  I need to set TREE_ASM_WRITTEN
on the VAR_DECLs to avoid them being output into assembly
(or should I teach cgraphunit.c that it shouldn't assemble_variable
vars with DECL_HAS_VALUE_EXPR_P set?), which works just fine for COMMON
vars (they are public and debug info is emitted during wraping up global
decls, they are also emitted always) or for non-SAVEd EQUIVALENCEs.
But for SAVEd EQUIVALENCEs which are function local static unions
the debug info for the variables should be only emitted if the
EQUIVALENCE has been/is going to be emitted and not if the union is
optimized out.  I see 2 ways to handle that, one is implemented in
the patch, i.e. gfc_expand_function walks over all variables in the
outermost function binding block (that's the only place where EQUIVALENCEs
are stored) and emits the dbeug info for them.  The other would be
to
1) teach middle-end that it should never emit DECL_HAS_VALUE_EXPR_P
   vars, just emit debug info for them
2) don't set TREE_ASM_WRITTEN in tree-common.c 
3) create a hash table that maps union VAR_DECLs to al the
   VAR_DECLs with DECL_HAS_VALUE_EXPR_P set that are COMPONENT_REFs of the
   union
4) write callgraph.analyze_expr hook that will mark the
   DECL_HAS_VALUE_EXPR_P vars needed if the union itself is marked needed
   by the cgraph varpool code
The f95-lang.c solution is certainly much shorter.

Tested on x86_64-linux.
Ok for HEAD?

2005-10-11  Jakub Jelinek  <jakub@redhat.com>

	* trans-common.c (build_field): Fix comment typo.
	(create_common): Set backend_decl of COMMON or EQUIVALENCEd
	variables to a VAR_DECL with the COMPONENT_REF in
	DECL_HAS_VALUE_EXPR rather than COMPONENT_REF directly.
	* f95-lang.c (gfc_expand_function): Emit debug info for
	EQUIVALENCEd variables if the equiv union is going to be output.

--- gcc/fortran/trans-common.c.jj	2005-09-27 21:51:53.000000000 +0200
+++ gcc/fortran/trans-common.c	2005-10-11 16:46:20.000000000 +0200
@@ -241,7 +241,7 @@ build_field (segment_info *h, tree union
                                         DECL_FIELD_OFFSET (field),
                                         DECL_SIZE_UNIT (field)));
   /* If this field is assigned to a label, we create another two variables.
-     One will hold the address of taget label or format label. The other will
+     One will hold the address of target label or format label. The other will
      hold the length of format label string.  */
   if (h->sym->attr.assign)
     {
@@ -471,8 +474,38 @@ create_common (gfc_common_head *com, seg
   /* Build component reference for each variable.  */
   for (s = head; s; s = next_s)
     {
-      s->sym->backend_decl = build3 (COMPONENT_REF, TREE_TYPE (s->field),
-				decl, s->field, NULL_TREE);
+      tree var_decl;
+
+      var_decl = build_decl (VAR_DECL, DECL_NAME (s->field),
+			     TREE_TYPE (s->field));
+      gfc_set_decl_location (var_decl, &s->sym->declared_at);
+      TREE_PUBLIC (var_decl) = TREE_PUBLIC (decl);
+      TREE_STATIC (var_decl) = TREE_STATIC (decl);
+      TREE_USED (var_decl) = TREE_USED (decl);
+      if (s->sym->attr.target)
+	TREE_ADDRESSABLE (var_decl) = 1;
+      /* This is a fake variable just for debugging purposes.  */
+      TREE_ASM_WRITTEN (var_decl) = 1;
+
+      if (com)
+	var_decl = pushdecl_top_level (var_decl);
+      else
+	gfc_add_decl_to_function (var_decl);
+
+      SET_DECL_VALUE_EXPR (var_decl,
+			   build3 (COMPONENT_REF, TREE_TYPE (s->field),
+				   decl, s->field, NULL_TREE));
+      DECL_HAS_VALUE_EXPR_P (var_decl) = 1;
+
+      if (s->sym->attr.assign)
+	{
+	  gfc_allocate_lang_decl (var_decl);
+	  GFC_DECL_ASSIGN (var_decl) = 1;
+	  GFC_DECL_STRING_LEN (var_decl) = GFC_DECL_STRING_LEN (s->field);
+	  GFC_DECL_ASSIGN_ADDR (var_decl) = GFC_DECL_ASSIGN_ADDR (s->field);
+	}
+
+      s->sym->backend_decl = var_decl;
 
       next_s = s->next;
       gfc_free (s);
--- gcc/fortran/f95-lang.c.jj	2005-10-04 19:23:13.000000000 +0200
+++ gcc/fortran/f95-lang.c	2005-10-11 16:29:42.000000000 +0200
@@ -187,6 +187,36 @@ tree *ridpointers = NULL;
 static void
 gfc_expand_function (tree fndecl)
 {
+  tree t;
+
+  if (DECL_INITIAL (fndecl)
+      && BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl)))
+    {
+      /* Local static equivalenced variables are never seen by
+	 check_global_declarations, so we need to output debug
+	 info by hand.  */
+
+      t = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl));
+      for (t = BLOCK_VARS (t); t; t = TREE_CHAIN (t))
+	if (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t)
+	    && TREE_STATIC (t))
+	  {
+	    tree expr = DECL_VALUE_EXPR (t);
+
+	    if (TREE_CODE (expr) == COMPONENT_REF
+		&& TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL
+		&& TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
+		   == UNION_TYPE
+		&& cgraph_varpool_node (TREE_OPERAND (expr, 0))->needed
+		&& errorcount == 0 && sorrycount == 0)
+	      {
+		timevar_push (TV_SYMOUT);
+		(*debug_hooks->global_decl) (t);
+		timevar_pop (TV_SYMOUT);
+	      }
+	  }
+    }
+
   tree_rest_of_compilation (fndecl);
 }
 


	Jakub



More information about the Gcc-patches mailing list