This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix PR 29609, being able to set a breakpoint on goto/continue/break
On 4/30/07, Tristan Gingold <gingold@adacore.com> wrote:
>> We cannot set a breakpoint on the 'goto' because there is no more
>> 'goto' in
>> the transformed code. My approach was to force the creation of a
>> BB for
>> the goto statement.
>
> And your approach is wrong if using goto_locus works instead.
I still do not understand your approach. You'd like to fix this
issue by correctly setting the locus. I think this is not enough
because there is
no proper generated instruction for the goto/exit/continue
statement. Look on this example:
if (i < 3)
break;
On linux/x86 this generates this code:
cmpl $3, -4(%ebp)
jle .L6
There is no proper insn for the goto statement. 'jle' will always be
executed.
The locus is on the edge, and we should put the locus from the edge on
the RTL jump. Since you don't understand this, I've just taken the
bug myself.
I've broken up the bug in three parts:
0) Show the location in the GIMPLE dumps with -fdump-tree-blah-lineno
1) Set the locus on JUMP_INSNs in cfgexpand
2) Don't use the locus across forwarder blocks
The attached patch tackes 0 and 1, as shown by this GDB session for
the test case in http://gcc.gnu.org/PR29609 :
steven@stevenb:~/devel/build-test/gcc> gdb a.out
GNU gdb 6.4
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-suse-linux"...Using host
libthread_db library "/lib64/tls/libthread_db.so.1".
Function "fancy_abort" not defined.
Function "internal_error" not defined.
Function "exit" not defined.
Function "abort" not defined.
(gdb) b 27
Breakpoint 1 at 0x4004fa: file t.c, line 27.
(gdb) b 30
Breakpoint 2 at 0x400503: file t.c, line 30.
(gdb) b 33
Breakpoint 3 at 0x40050c: file t.c, line 33.
(gdb) b 36
Breakpoint 4 at 0x400515: file t.c, line 36.
(gdb) run
Starting program: /home/steven/devel/build-test/gcc/a.out
Breakpoint 1, main (argc=1, argv=0x7fffff953dc8) at t.c:27
27 goto failure;
(gdb) cont
Continuing.
Breakpoint 2, main (argc=1, argv=0x7fffff953dc8) at t.c:30
30 goto failure;
(gdb)
Continuing.
Breakpoint 3, main (argc=1, argv=0x7fffff953dc8) at t.c:33
33 goto failure;
(gdb)
Continuing.
Program exited with code 01.
(gdb)
We still can't put a breakpoint on line 36 because we lose the locus
when we fall through from the goto on that line to the "success"
label. I don't have a patch for that yet.
The attached patch is not yet tested, but I hope it clarifies for you
what I mean with this goto_locus hocus pocus.
Gr.
Steven
Index: tree-pretty-print.c
===================================================================
--- tree-pretty-print.c (revision 124292)
+++ tree-pretty-print.c (working copy)
@@ -111,6 +111,20 @@ debug_tree_chain (tree t)
fprintf (stderr, "\n");
}
+/* Prints the locus of NODE to BUFFER. */
+static void
+print_locus (pretty_printer *buffer, expanded_location xloc)
+{
+ pp_character (buffer, '[');
+ if (xloc.file)
+ {
+ pp_string (buffer, xloc.file);
+ pp_string (buffer, " : ");
+ }
+ pp_decimal_int (buffer, xloc.line);
+ pp_string (buffer, "] ");
+}
+
/* Prints declaration DECL to the FILE with details specified by FLAGS. */
void
print_generic_decl (FILE *file, tree decl, int flags)
@@ -466,14 +480,7 @@ dump_generic_node (pretty_printer *buffe
if ((flags & TDF_LINENO) && EXPR_HAS_LOCATION (node))
{
expanded_location xloc = expand_location (EXPR_LOCATION (node));
- pp_character (buffer, '[');
- if (xloc.file)
- {
- pp_string (buffer, xloc.file);
- pp_string (buffer, " : ");
- }
- pp_decimal_int (buffer, xloc.line);
- pp_string (buffer, "] ");
+ print_locus (buffer, xloc);
}
switch (TREE_CODE (node))
@@ -2973,10 +2980,21 @@ dump_implicit_edges (pretty_printer *buf
extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
INDENT (indent + 2);
+
+ if ((flags & TDF_LINENO) && true_edge->goto_locus)
+ {
+ expanded_location xloc = expand_location (*true_edge->goto_locus);
+ print_locus (buffer, xloc);
+ }
pp_cfg_jump (buffer, true_edge->dest);
newline_and_indent (buffer, indent);
pp_string (buffer, "else");
newline_and_indent (buffer, indent + 2);
+ if ((flags & TDF_LINENO) && false_edge->goto_locus)
+ {
+ expanded_location xloc = expand_location (*false_edge->goto_locus);
+ print_locus (buffer, xloc);
+ }
pp_cfg_jump (buffer, false_edge->dest);
pp_newline (buffer);
return;
@@ -2999,20 +3017,8 @@ dump_implicit_edges (pretty_printer *buf
#endif
)
{
- expanded_location goto_xloc;
-#ifdef USE_MAPPED_LOCATION
- goto_xloc = expand_location (e->goto_locus);
-#else
- goto_xloc = *e->goto_locus;
-#endif
- pp_character (buffer, '[');
- if (goto_xloc.file)
- {
- pp_string (buffer, goto_xloc.file);
- pp_string (buffer, " : ");
- }
- pp_decimal_int (buffer, goto_xloc.line);
- pp_string (buffer, "] ");
+ expanded_location goto_xloc = expand_location (*e->goto_locus);
+ print_locus (buffer, goto_xloc);
}
pp_cfg_jump (buffer, e->dest);
Index: cfgexpand.c
===================================================================
--- cfgexpand.c (revision 124292)
+++ cfgexpand.c (working copy)
@@ -1276,6 +1276,27 @@ label_rtx_for_bb (basic_block bb)
return label_rtx (lab);
}
+/* A subroutine of jump expanders. Annotate all JUMP_INSNs in INSNS with
+ the location on the edge E, if one is present. Assumes INSNS is a NULL
+ terminated sequence of insns. */
+static void
+expand_gimple_edge_locus_on_jumps (rtx insns, edge e)
+{
+ rtx p;
+ int loc;
+
+ /* If there was a goto implicit in the edge, annotate all JUMP_INSNs
+ with that locus. */
+ if (! e->goto_locus)
+ return;
+
+ set_curr_insn_source_location (*e->goto_locus);
+ loc = curr_insn_locator ();
+ for (p = insns; p; p = NEXT_INSN (p))
+ if (JUMP_P (p))
+ INSN_LOCATOR (p) = loc;
+}
+
/* A subroutine of expand_gimple_basic_block. Expand one COND_EXPR.
Returns a new basic block if we've terminated the current basic
block and created a new one. */
@@ -1288,7 +1309,7 @@ expand_gimple_cond_expr (basic_block bb,
edge true_edge;
edge false_edge;
tree pred = COND_EXPR_COND (stmt);
- rtx last2, last;
+ rtx last2, last, insns;
gcc_assert (COND_EXPR_THEN (stmt) == NULL_TREE);
gcc_assert (COND_EXPR_ELSE (stmt) == NULL_TREE);
@@ -1309,29 +1330,46 @@ expand_gimple_cond_expr (basic_block bb,
two-way jump that needs to be decomposed into two basic blocks. */
if (false_edge->dest == bb->next_bb)
{
+ false_edge->flags |= EDGE_FALLTHRU;
+ start_sequence ();
jumpif (pred, label_rtx_for_bb (true_edge->dest));
+ insns = get_insns ();
+ end_sequence ();
+ expand_gimple_edge_locus_on_jumps (insns, true_edge);
+ emit_insn_after_noloc (insns, last);
add_reg_br_prob_note (last, true_edge->probability);
maybe_dump_rtl_for_tree_stmt (stmt, last);
- if (true_edge->goto_locus)
- set_curr_insn_source_location (*true_edge->goto_locus);
- false_edge->flags |= EDGE_FALLTHRU;
return NULL;
}
if (true_edge->dest == bb->next_bb)
{
+ true_edge->flags |= EDGE_FALLTHRU;
+ start_sequence ();
jumpifnot (pred, label_rtx_for_bb (false_edge->dest));
+ insns = get_insns ();
+ end_sequence ();
+ expand_gimple_edge_locus_on_jumps (insns, false_edge);
+ emit_insn_after_noloc (insns, last);
add_reg_br_prob_note (last, false_edge->probability);
maybe_dump_rtl_for_tree_stmt (stmt, last);
- if (false_edge->goto_locus)
- set_curr_insn_source_location (*false_edge->goto_locus);
- true_edge->flags |= EDGE_FALLTHRU;
return NULL;
}
+ start_sequence ();
jumpif (pred, label_rtx_for_bb (true_edge->dest));
+ insns = get_insns ();
+ end_sequence ();
+ expand_gimple_edge_locus_on_jumps (insns, true_edge);
+ emit_insn_after_noloc (insns, last);
add_reg_br_prob_note (last, true_edge->probability);
last = get_last_insn ();
+
+ start_sequence ();
emit_jump (label_rtx_for_bb (false_edge->dest));
+ insns = get_insns ();
+ end_sequence ();
+ expand_gimple_edge_locus_on_jumps (insns, false_edge);
+ emit_insn_after_noloc (insns, last);
BB_END (bb) = last;
if (BARRIER_P (BB_END (bb)))
@@ -1353,9 +1391,6 @@ expand_gimple_cond_expr (basic_block bb,
maybe_dump_rtl_for_tree_stmt (stmt, last2);
- if (false_edge->goto_locus)
- set_curr_insn_source_location (*false_edge->goto_locus);
-
return new_bb;
}
@@ -1603,13 +1638,18 @@ expand_gimple_basic_block (basic_block b
if (e->flags & EDGE_FALLTHRU)
break;
}
-
if (e && e->dest != bb->next_bb)
{
- emit_jump (label_rtx_for_bb (e->dest));
- if (e->goto_locus)
- set_curr_insn_source_location (*e->goto_locus);
+ rtx insns;
+
+ last = get_last_insn ();
e->flags &= ~EDGE_FALLTHRU;
+ start_sequence ();
+ emit_jump (label_rtx_for_bb (e->dest));
+ insns = get_insns ();
+ end_sequence ();
+ expand_gimple_edge_locus_on_jumps (insns, e);
+ emit_insn_after_noloc (insns, last);
}
do_pending_stack_adjust ();