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:
parent
ff7a55bf56
commit
f2834b5d87
@ -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>
|
2015-12-02 Tom de Vries <tom@codesourcery.com>
|
||||||
|
|
||||||
* gimplify.c (enum gimplify_omp_var_data): Add enum value
|
* gimplify.c (enum gimplify_omp_var_data): Add enum value
|
||||||
|
@ -19268,7 +19268,9 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
|
|||||||
rtx tloc = NULL_RTX, tlocc = NULL_RTX;
|
rtx tloc = NULL_RTX, tlocc = NULL_RTX;
|
||||||
rtx arg, next_arg;
|
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)
|
arg; arg = next_arg)
|
||||||
{
|
{
|
||||||
dw_loc_descr_ref reg, val;
|
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)
|
if (mode == VOIDmode || mode == BLKmode)
|
||||||
continue;
|
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);
|
if (XEXP (XEXP (arg, 0), 0) == pc_rtx)
|
||||||
tloc = XEXP (XEXP (arg, 0), 1);
|
{
|
||||||
continue;
|
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)
|
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);
|
tlocc = XEXP (XEXP (arg, 0), 1);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
reg = NULL;
|
reg = NULL;
|
||||||
if (REG_P (XEXP (XEXP (arg, 0), 0)))
|
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];
|
char loclabel[MAX_ARTIFICIAL_LABEL_BYTES + 2];
|
||||||
struct var_loc_node *newloc;
|
struct var_loc_node *newloc;
|
||||||
rtx_insn *next_real, *next_note;
|
rtx_insn *next_real, *next_note;
|
||||||
|
rtx_insn *call_insn = NULL;
|
||||||
static const char *last_label;
|
static const char *last_label;
|
||||||
static const char *last_postcall_label;
|
static const char *last_postcall_label;
|
||||||
static bool last_in_cold_section_p;
|
static bool last_in_cold_section_p;
|
||||||
@ -22303,6 +22311,35 @@ dwarf2out_var_location (rtx_insn *loc_note)
|
|||||||
call_site_count++;
|
call_site_count++;
|
||||||
if (SIBLING_CALL_P (loc_note))
|
if (SIBLING_CALL_P (loc_note))
|
||||||
tail_call_site_count++;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
@ -22348,6 +22385,8 @@ dwarf2out_var_location (rtx_insn *loc_note)
|
|||||||
&& !NOTE_DURING_CALL_P (loc_note))
|
&& !NOTE_DURING_CALL_P (loc_note))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
create_label:
|
||||||
|
|
||||||
if (next_real == NULL_RTX)
|
if (next_real == NULL_RTX)
|
||||||
next_real = get_last_insn ();
|
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)
|
if (!var_loc_p)
|
||||||
{
|
{
|
||||||
struct call_arg_loc_node *ca_loc
|
struct call_arg_loc_node *ca_loc
|
||||||
= ggc_cleared_alloc<call_arg_loc_node> ();
|
= ggc_cleared_alloc<call_arg_loc_node> ();
|
||||||
rtx_insn *prev = prev_real_insn (loc_note);
|
rtx_insn *prev
|
||||||
rtx x;
|
= loc_note != NULL_RTX ? prev_real_insn (loc_note) : call_insn;
|
||||||
|
|
||||||
ca_loc->call_arg_loc_note = loc_note;
|
ca_loc->call_arg_loc_note = loc_note;
|
||||||
ca_loc->next = NULL;
|
ca_loc->next = NULL;
|
||||||
ca_loc->label = last_label;
|
ca_loc->label = last_label;
|
||||||
@ -22444,15 +22487,27 @@ dwarf2out_var_location (rtx_insn *loc_note)
|
|||||||
if (!CALL_P (prev))
|
if (!CALL_P (prev))
|
||||||
prev = as_a <rtx_sequence *> (PATTERN (prev))->insn (0);
|
prev = as_a <rtx_sequence *> (PATTERN (prev))->insn (0);
|
||||||
ca_loc->tail_call_p = SIBLING_CALL_P (prev);
|
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)
|
if (x)
|
||||||
{
|
{
|
||||||
x = XEXP (XEXP (x, 0), 0);
|
/* Try to get the call symbol, if any. */
|
||||||
if (GET_CODE (x) == SYMBOL_REF
|
if (MEM_P (XEXP (x, 0)))
|
||||||
&& SYMBOL_REF_DECL (x)
|
x = XEXP (x, 0);
|
||||||
&& TREE_CODE (SYMBOL_REF_DECL (x)) == FUNCTION_DECL)
|
/* First, look for a memory access to a symbol_ref. */
|
||||||
ca_loc->symbol_ref = x;
|
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);
|
ca_loc->block = insn_scope (prev);
|
||||||
if (call_arg_locations)
|
if (call_arg_locations)
|
||||||
call_arg_loc_last->next = ca_loc;
|
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_locations = ca_loc;
|
||||||
call_arg_loc_last = 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;
|
newloc->label = last_label;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
11
gcc/final.c
11
gcc/final.c
@ -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)
|
||||||
targetm.asm_out.unwind_emit (asm_out_file, insn);
|
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);
|
rtx x = call_from_call_insn (call_insn);
|
||||||
x = XEXP (x, 0);
|
x = XEXP (x, 0);
|
||||||
@ -3007,8 +3008,6 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
|
|||||||
if (t)
|
if (t)
|
||||||
assemble_external (t);
|
assemble_external (t);
|
||||||
}
|
}
|
||||||
if (!DECL_IGNORED_P (current_function_decl))
|
|
||||||
debug_hooks->var_location (insn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Output assembler code from the template. */
|
/* 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)
|
||||||
targetm.asm_out.unwind_emit (asm_out_file, insn);
|
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;
|
current_output_insn = debug_insn = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user