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(-)
@@ -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)
@@ -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);
@@ -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,
@@ -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);
@@ -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
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!