This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH, PING*4] Track indirect calls for call site information in debug info.


On 11/23/2015 10:11 PM, Jason Merrill wrote:
Jakub, since DW_TAG_GNU_call_site is your feature, could you review this?

As Jeff Law suggested in the âGCC 6 Status Reportâ thread, Iâve added Alexandre Oliva to the discussion to review the var-tracking part.

Also, Iâve rebased+bootstrapped+regtested the patch: the updated version is attached.

Thanks in advance for your review!

--
Pierre-Marie de Rodat
>From 2a02ebc79b51693a341355a2301dc0f733591930 Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Thu, 13 Jun 2013 11:13:08 +0200
Subject: [PATCH] Track indirect calls for call site information in debug info.

gcc/ChangeLog:

	* passes.def: Add a new pass: variable_tracking_no_opt.
	* rtl.h (variable_tracking_no_opt_main): New.
	* tree-pass.h (make_pass_variable_tracking_no_opt): New.
	* var-tracking.c (variable_tracking_no_opt_main,
	pass_data_variable_tracking_no_opt,
	pass_variable_tracking_no_opt,
	make_pass_variable_tracking_no_opt): New.  Implement the new
	pass which adds notes for indirect calls.
	* dwarf2out.c (dwarf2out_var_location): Set the symbol reference
	for calls whose target is compile-time known but that are
	indirect.
	(gen_subprogram_die): Handle such calls.
---
 gcc/dwarf2out.c    |  46 +++++++++++++++---------
 gcc/passes.def     |   1 +
 gcc/rtl.h          |   1 +
 gcc/tree-pass.h    |   1 +
 gcc/var-tracking.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 135 insertions(+), 16 deletions(-)

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index f184750..c8c37ff 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -19277,18 +19277,23 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
 		    }
 		  if (mode == VOIDmode || mode == BLKmode)
 		    continue;
-		  if (XEXP (XEXP (arg, 0), 0) == pc_rtx)
+		  /* Sometimes, the target of a call is compile-time known, but
+		     for various reasons, there is still an indirect call
+		     instruction: do not output redundant debug information for
+		     them.  */
+		  if (ca_loc->symbol_ref == NULL_RTX)
 		    {
-		      gcc_assert (ca_loc->symbol_ref == NULL_RTX);
-		      tloc = XEXP (XEXP (arg, 0), 1);
-		      continue;
-		    }
-		  else if (GET_CODE (XEXP (XEXP (arg, 0), 0)) == CLOBBER
-			   && XEXP (XEXP (XEXP (arg, 0), 0), 0) == pc_rtx)
-		    {
-		      gcc_assert (ca_loc->symbol_ref == NULL_RTX);
-		      tlocc = XEXP (XEXP (arg, 0), 1);
-		      continue;
+		      if (XEXP (XEXP (arg, 0), 0) == pc_rtx)
+			{
+			  tloc = XEXP (XEXP (arg, 0), 1);
+			  continue;
+			}
+		      else if (GET_CODE (XEXP (XEXP (arg, 0), 0)) == CLOBBER
+			       && XEXP (XEXP (XEXP (arg, 0), 0), 0) == pc_rtx)
+			{
+			  tlocc = XEXP (XEXP (arg, 0), 1);
+			  continue;
+			}
 		    }
 		  reg = NULL;
 		  if (REG_P (XEXP (XEXP (arg, 0), 0)))
@@ -22428,11 +22433,20 @@ dwarf2out_var_location (rtx_insn *loc_note)
       x = get_call_rtx_from (PATTERN (prev));
       if (x)
 	{
-	  x = XEXP (XEXP (x, 0), 0);
-	  if (GET_CODE (x) == SYMBOL_REF
-	      && SYMBOL_REF_DECL (x)
-	      && TREE_CODE (SYMBOL_REF_DECL (x)) == FUNCTION_DECL)
-	    ca_loc->symbol_ref = x;
+	  /* Try to get the call symbol, if any.  */
+	  if (MEM_P (XEXP (x, 0)))
+	    x = XEXP (x, 0);
+	  /* First, look for a memory access to a symbol_ref.  */
+	  if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF
+	      && SYMBOL_REF_DECL (XEXP (x, 0))
+	      && TREE_CODE (SYMBOL_REF_DECL (XEXP (x, 0))) == FUNCTION_DECL)
+	    ca_loc->symbol_ref = XEXP (x, 0);
+	  /* Otherwise, look at a compile-time known user-level function
+	     declaration.  */
+	  else if (MEM_P (x)
+		   && MEM_EXPR (x)
+		   && TREE_CODE (MEM_EXPR (x)) == FUNCTION_DECL)
+	    ca_loc->symbol_ref = XEXP (DECL_RTL (MEM_EXPR (x)), 0);
 	}
       ca_loc->block = insn_scope (prev);
       if (call_arg_locations)
diff --git a/gcc/passes.def b/gcc/passes.def
index 1702778..2c4ecc6 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -449,6 +449,7 @@ along with GCC; see the file COPYING3.  If not see
       PUSH_INSERT_PASSES_WITHIN (pass_late_compilation)
 	  NEXT_PASS (pass_compute_alignments);
 	  NEXT_PASS (pass_variable_tracking);
+	  NEXT_PASS (pass_variable_tracking_no_opt);
 	  NEXT_PASS (pass_free_cfg);
 	  NEXT_PASS (pass_machine_reorg);
 	  NEXT_PASS (pass_cleanup_barriers);
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 194ed9b..7f54605 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -3673,6 +3673,7 @@ extern GTY(()) rtx stack_limit_rtx;
 
 /* In var-tracking.c */
 extern unsigned int variable_tracking_main (void);
+extern unsigned int variable_tracking_no_opt_main (void);
 
 /* In stor-layout.c.  */
 extern void get_mode_bounds (machine_mode, int, machine_mode,
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index dcd2d5e..33d9218 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -589,6 +589,7 @@ extern rtl_opt_pass *make_pass_df_finish (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_compute_alignments (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_duplicate_computed_gotos (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_variable_tracking (gcc::context *ctxt);
+extern rtl_opt_pass *make_pass_variable_tracking_no_opt (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_free_cfg (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_machine_reorg (gcc::context *ctxt);
 extern rtl_opt_pass *make_pass_cleanup_barriers (gcc::context *ctxt);
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 9185bfd..2103d87 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -114,6 +114,7 @@
 #include "tree-pretty-print.h"
 #include "rtl-iter.h"
 #include "fibonacci_heap.h"
+#include "debug.h"
 
 typedef fibonacci_heap <long, basic_block_def> bb_heap_t;
 typedef fibonacci_node <long, basic_block_def> bb_heap_node_t;
@@ -10284,6 +10285,61 @@ variable_tracking_main (void)
   return ret;
 }
 
+/* Entry point for the naive variable tracking pass.  Add notes for indirect
+   calls in each basic block.  */
+
+unsigned int
+variable_tracking_no_opt_main (void)
+{
+  basic_block bb;
+
+  /* Look for every call instruction and add an empty note right after
+     them if needed.  */
+  FOR_EACH_BB_FN (bb, cfun)
+    {
+      rtx_insn *insn;
+
+      FOR_BB_INSNS (bb, insn)
+	{
+	  rtx x;
+
+	  /* We are at -O0 so do not bother about dealing with SEQUENCEs.  */
+	  if (!INSN_P (insn))
+	    continue;
+	  x = PATTERN (insn);
+	  if (GET_CODE (x) == PARALLEL)
+	    x = XVECEXP (x, 0, 0);
+	  if (GET_CODE (x) == SET)
+	    x = SET_SRC (x);
+	  if (GET_CODE (x) == CALL)
+	    {
+	      x = XEXP (x, 0);
+
+	      /* The purpose of this pass is to add notes after some call
+		 instructions so that debug info is generated for them.  The
+		 goal is to make it possible to get the call target by looking
+		 either at the call instruction or, when this is not sufficient
+		 (like with indirect calls), at the corresponding debug
+		 information.  */
+	      if (!MEM_P (x)
+		  || GET_CODE (XEXP (x, 0)) != SYMBOL_REF
+		  || !SYMBOL_REF_DECL (XEXP (x, 0))
+		  || (TREE_CODE (SYMBOL_REF_DECL (XEXP (x, 0)))
+		      != FUNCTION_DECL))
+		{
+		  /* Emit a not only for calls that have a pattern that is not:
+		     (call (mem (symbol_ref some_function_decl))).  */
+		  rtx note
+		    = emit_note_after (NOTE_INSN_CALL_ARG_LOCATION, insn);
+		  NOTE_VAR_LOCATION (note) = NULL;
+		}
+	    }
+	}
+    }
+
+  return 0;
+}
+
 namespace {
 
 const pass_data pass_data_variable_tracking =
@@ -10319,6 +10375,46 @@ public:
 
 }; // class pass_variable_tracking
 
+const pass_data pass_data_variable_tracking_no_opt =
+{
+  RTL_PASS, /* type */
+  "no-opt vartrack", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_VAR_TRACKING,/* tv_id */
+  0, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  0 /* todo_flags_finish */
+};
+
+class pass_variable_tracking_no_opt : public rtl_opt_pass
+{
+public:
+  pass_variable_tracking_no_opt (gcc::context *ctxt)
+    : rtl_opt_pass (pass_data_variable_tracking_no_opt, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *)
+    {
+      /* This pass replaces the regular var-tracking pass when it is not
+	 enabled, but only at -O0 (by default, the var-tracking pass is
+	 disabled at -O0 only).  It is useful only when producing debug
+	 information.  */
+      return (optimize == 0
+	      && !flag_var_tracking
+	      && debug_info_level >= DINFO_LEVEL_NORMAL
+	      && (debug_hooks->var_location
+		  != do_nothing_debug_hooks.var_location));
+    }
+
+  virtual unsigned int execute (function *)
+    {
+      return variable_tracking_no_opt_main ();
+    }
+}; // class pass_variable_tracking_no_opt
+
 } // anon namespace
 
 rtl_opt_pass *
@@ -10326,3 +10422,9 @@ make_pass_variable_tracking (gcc::context *ctxt)
 {
   return new pass_variable_tracking (ctxt);
 }
+
+rtl_opt_pass *
+make_pass_variable_tracking_no_opt (gcc::context *ctxt)
+{
+  return new pass_variable_tracking_no_opt (ctxt);
+}
-- 
2.3.3.199.g52cae64


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]