public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Track indirect calls for call site information in debug info.
@ 2015-07-20 13:02 Pierre-Marie de Rodat
  2015-07-27  9:13 ` [PATCH, PING] " Pierre-Marie de Rodat
  0 siblings, 1 reply; 12+ messages in thread
From: Pierre-Marie de Rodat @ 2015-07-20 13:02 UTC (permalink / raw)
  To: GCC Patches

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

Hello,

On PowerPC targets with -mlongcall, most subprogram calls are turned 
into indirect calls: the call target is read from a register even though 
it is compile-time known. This makes it difficult for machine code 
static analysis engines to recover the callee information. The attached 
patch is an attempt to help such engines, generating 
DW_AT_abstract_origin attributes for all DW_TAG_GNU_call_site we are 
interested in.

Here is how it works:

    1. At -O0, the var-tracking pass is disabled, so in order to get a 
NOTE_INSN_CALL_ARG_LOCATION for each call we are interested in, this 
patch creates a new "naive" var-tracking pass. When optimizing, the 
regular var-tracking pass does this job and this new pass is disabled.

    2. The DWARF back-end (dwarf2out.c) first registers this RTL note 
(in dwarf2out_var_location, already existing code) and extracts the 
corresponding callee function symbol reference (new code to add handling 
for the case we are interested in).

       There, the patch also relaxes assertions in gen_subprogram_die: 
yes, we can have both a compile-time known call target and an indirect 
call. Already existing code in gen_subprogram_die calls 
gen_call_site_die and takes care of generating the corresponding debug 
information.

Bootstrapped and regtested on x86_64-pc-linux-gnu and powerpc-linux-gnu: 
no regression. Ok for trunk? Thank you in advance for your feedback!

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.

-- 
Pierre-Marie de Rodat


[-- Attachment #2: 0001-Track-indirect-calls-for-call-site-information-in-de.patch --]
[-- Type: text/x-diff, Size: 8596 bytes --]

From 1fee786f51baca25f1363cd82f207cd67f48e69f 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 2834d57..a6bcb48 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -19219,18 +19219,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)))
@@ -22344,11 +22349,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 6b66f8f..d65e380 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -446,6 +446,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 f363ed4..5be307d 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -3648,6 +3648,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 c47b22e..67ad558 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -576,6 +576,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 da9de28..03187f9 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -121,6 +121,7 @@
 #include "recog.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;
@@ -10325,6 +10326,61 @@ variable_tracking_main (void)
   return ret;
 }
 \f
+/* 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;
+}
+\f
 namespace {
 
 const pass_data pass_data_variable_tracking =
@@ -10360,6 +10416,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 *
@@ -10367,3 +10463,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.4.5


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

end of thread, other threads:[~2015-12-02 15:58 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-20 13:02 [PATCH] Track indirect calls for call site information in debug info Pierre-Marie de Rodat
2015-07-27  9:13 ` [PATCH, PING] " Pierre-Marie de Rodat
2015-08-03  8:41   ` [PATCH, PING*2] " Pierre-Marie de Rodat
2015-08-08  9:53     ` [PATCH, PING*3] " Pierre-Marie de Rodat
2015-08-31  7:29       ` [PATCH, PING*4] " Pierre-Marie de Rodat
2015-11-23 21:18         ` Jason Merrill
2015-11-24 16:33           ` Pierre-Marie de Rodat
2015-11-24 17:22             ` Jakub Jelinek
2015-11-30 11:14               ` Pierre-Marie de Rodat
2015-12-02 13:46               ` Pierre-Marie de Rodat
2015-12-02 13:57                 ` Jakub Jelinek
2015-12-02 15:58                   ` 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).