Track indirect calls for call site information in debug info

gcc/ChangeLog:

	* dwarf2out.c (dwar2out_var_location): In addition to notes,
	process indirect calls whose target is compile-time known.
	Enhance pattern matching to get the SYMBOL_REF they embed.
	(gen_subprogram_die): Handle such calls.
	* final.c (final_scan_insn): For call instructions, invoke the
	var_location debug hook only after the call has been emitted.

From-SVN: r231185
This commit is contained in:
Pierre-Marie de Rodat 2015-12-02 15:57:34 +00:00 committed by Pierre-Marie de Rodat
parent ff7a55bf56
commit f2834b5d87
3 changed files with 93 additions and 24 deletions

View File

@ -1,3 +1,12 @@
2015-12-02 Pierre-Marie de Rodat <derodat@adacore.com>
* dwarf2out.c (dwar2out_var_location): In addition to notes,
process indirect calls whose target is compile-time known.
Enhance pattern matching to get the SYMBOL_REF they embed.
(gen_subprogram_die): Handle such calls.
* final.c (final_scan_insn): For call instructions, invoke the
var_location debug hook only after the call has been emitted.
2015-12-02 Tom de Vries <tom@codesourcery.com>
* gimplify.c (enum gimplify_omp_var_data): Add enum value

View File

@ -19268,7 +19268,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
rtx tloc = NULL_RTX, tlocc = NULL_RTX;
rtx arg, next_arg;
for (arg = NOTE_VAR_LOCATION (ca_loc->call_arg_loc_note);
for (arg = (ca_loc->call_arg_loc_note != NULL_RTX
? NOTE_VAR_LOCATION (ca_loc->call_arg_loc_note)
: NULL_RTX);
arg; arg = next_arg)
{
dw_loc_descr_ref reg, val;
@ -19291,18 +19293,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)
/* Get dynamic information about call target only if we
have no static information: we cannot generate both
DW_AT_abstract_origin and DW_AT_GNU_call_site_target
attributes. */
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)))
@ -22289,6 +22296,7 @@ dwarf2out_var_location (rtx_insn *loc_note)
char loclabel[MAX_ARTIFICIAL_LABEL_BYTES + 2];
struct var_loc_node *newloc;
rtx_insn *next_real, *next_note;
rtx_insn *call_insn = NULL;
static const char *last_label;
static const char *last_postcall_label;
static bool last_in_cold_section_p;
@ -22303,6 +22311,35 @@ dwarf2out_var_location (rtx_insn *loc_note)
call_site_count++;
if (SIBLING_CALL_P (loc_note))
tail_call_site_count++;
if (optimize == 0 && !flag_var_tracking)
{
/* When the var-tracking pass is not running, there is no note
for indirect calls whose target is compile-time known. In this
case, process such calls specifically so that we generate call
sites for them anyway. */
rtx x = PATTERN (loc_note);
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);
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))
{
call_insn = loc_note;
loc_note = NULL;
var_loc_p = false;
next_real = next_real_insn (call_insn);
next_note = NULL;
cached_next_real_insn = NULL;
goto create_label;
}
}
}
return;
}
@ -22348,6 +22385,8 @@ dwarf2out_var_location (rtx_insn *loc_note)
&& !NOTE_DURING_CALL_P (loc_note))
return;
create_label:
if (next_real == NULL_RTX)
next_real = get_last_insn ();
@ -22427,12 +22466,16 @@ dwarf2out_var_location (rtx_insn *loc_note)
}
}
gcc_assert ((loc_note == NULL_RTX && call_insn != NULL_RTX)
|| (loc_note != NULL_RTX && call_insn == NULL_RTX));
if (!var_loc_p)
{
struct call_arg_loc_node *ca_loc
= ggc_cleared_alloc<call_arg_loc_node> ();
rtx_insn *prev = prev_real_insn (loc_note);
rtx x;
rtx_insn *prev
= loc_note != NULL_RTX ? prev_real_insn (loc_note) : call_insn;
ca_loc->call_arg_loc_note = loc_note;
ca_loc->next = NULL;
ca_loc->label = last_label;
@ -22444,15 +22487,27 @@ dwarf2out_var_location (rtx_insn *loc_note)
if (!CALL_P (prev))
prev = as_a <rtx_sequence *> (PATTERN (prev))->insn (0);
ca_loc->tail_call_p = SIBLING_CALL_P (prev);
x = get_call_rtx_from (PATTERN (prev));
/* Look for a SYMBOL_REF in the "prev" instruction. */
rtx 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)
call_arg_loc_last->next = ca_loc;
@ -22460,7 +22515,7 @@ dwarf2out_var_location (rtx_insn *loc_note)
call_arg_locations = ca_loc;
call_arg_loc_last = ca_loc;
}
else if (!NOTE_DURING_CALL_P (loc_note))
else if (loc_note != NULL_RTX && !NOTE_DURING_CALL_P (loc_note))
newloc->label = last_label;
else
{

View File

@ -2995,7 +2995,8 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
&& targetm.asm_out.unwind_emit)
targetm.asm_out.unwind_emit (asm_out_file, insn);
if (rtx_call_insn *call_insn = dyn_cast <rtx_call_insn *> (insn))
rtx_call_insn *call_insn = dyn_cast <rtx_call_insn *> (insn);
if (call_insn != NULL)
{
rtx x = call_from_call_insn (call_insn);
x = XEXP (x, 0);
@ -3007,8 +3008,6 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
if (t)
assemble_external (t);
}
if (!DECL_IGNORED_P (current_function_decl))
debug_hooks->var_location (insn);
}
/* Output assembler code from the template. */
@ -3024,6 +3023,12 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
&& targetm.asm_out.unwind_emit)
targetm.asm_out.unwind_emit (asm_out_file, insn);
/* Let the debug info back-end know about this call. We do this only
after the instruction has been emitted because labels that may be
created to reference the call instruction must appear after it. */
if (call_insn != NULL && !DECL_IGNORED_P (current_function_decl))
debug_hooks->var_location (insn);
current_output_insn = debug_insn = 0;
}
}