summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpmderodat <pmderodat@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-02 15:57:34 +0000
committerpmderodat <pmderodat@138bc75d-0d04-0410-961f-82ee72b054a4>2015-12-02 15:57:34 +0000
commit24096e16648248c1f069aab4b74f4765bfdbe216 (patch)
treea32dc57ea24048ca49e8b206953e1025378e8dc7
parent2a7545d57731de7d4918a8786c972259488dbc56 (diff)
downloadgcc-24096e16648248c1f069aab4b74f4765bfdbe216.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@231185 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/dwarf2out.c97
-rw-r--r--gcc/final.c11
3 files changed, 93 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ef5fbefd7b4..ca0b22e452a 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 357f1148ede..6af57b58864 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -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
{
diff --git a/gcc/final.c b/gcc/final.c
index 2f57b1bc3f1..8cb55332e3d 100644
--- a/gcc/final.c
+++ b/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 (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;
}
}