This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Committed: verify_flow_info fixes exposed by libgfortran (at leaston MMIX)
- From: Hans-Peter Nilsson <hp at bitrange dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 17 Oct 2004 21:58:27 -0400 (EDT)
- Subject: Committed: verify_flow_info fixes exposed by libgfortran (at leaston MMIX)
I worked around the stdint.h issue for libgfortran cross to newlib
targets, specifically mmix-knuth-mmixware. A build then crashes for
really bad reasons:
/home/hp/builds2/mmixware-sim/gcc/xgcc -B/home/hp/builds2/mmixware-sim/gcc/ -nostdinc -B/home/hp/builds2/mmixware-sim/mmix/newlib\
/ -isystem /home/hp/builds2/mmixware-sim/mmix/newlib/targ-include -isystem /home/hp/cvs_areas/combined/cvs_write/newlib/libc/incl\
ude -B/home/hp/builds2/mmixware-sim/../install-mmix/mmix/bin/ -B/home/hp/builds2/mmixware-sim/../install-mmix/mmix/lib/ -isystem \
/home/hp/builds2/mmixware-sim/../install-mmix/mmix/include -isystem /home/hp/builds2/mmixware-sim/../install-mmix/mmix/sys-includ\
e -L/home/hp/builds2/mmixware-sim/ld -DHAVE_CONFIG_H -I. -I/home/hp/cvs_areas/combined/cvs_write/libgfortran -I. -I/home/hp/cvs_a\
reas/combined/cvs_write/libgfortran/io -O2 -g -O2 -std=gnu99 -O2 -g -O2 -c /home/hp/cvs_areas/combined/cvs_write/libgfortran/io/l\
ist_read.c -o list_read.o
(barrier 89 87 88)
/home/hp/cvs_areas/combined/cvs_write/libgfortran/io/list_read.c: In function 'next_char':
/home/hp/cvs_areas/combined/cvs_write/libgfortran/io/list_read.c:160: internal compiler error: Segmentation fault
There are two bugs here. The segmentation fault is because BLOCK_FOR_INSN
for a barrier is never set; it contains 0xafafafaf GGC markers. Thus the
debug code, handling NULL:s but not bad pointers, crashes referencing
(struct basic_block_def *) 0xafafafaf trying to emit debug-output for that
bb. Comparing with emit_note, it's obvious that BLOCK_FOR_INSN for
barriers should be set (well, cleared) at creation of barriers. Code that
is supposed to set BLOCK_FOR_INSN skips barriers.
The other bug is that rtl_verify_flow_info_1 doesn't allow a barrier in a
bb. It's obvious from looking at control_flow_insn_p (called in another
iteration over insns in a bb in rtl_verify_flow_info_1) that barriers are
valid here:
case BARRIER:
/* It is nonsense to reach barrier when looking for the
end of basic block, but before dead code is eliminated
this may happen. */
Which is spot on.
The actual reason there's a barrier in this bb is that "call" for mmix
expands to two insns: the call itself and a return-address-register
restore. The call is to longjmp, so there's a barrier (validly) emitted
after the actual call insn. Because the barrier is not *last* in the
sequence, it is not skipped when setting the bb head and end pointers.
This is at tree-expand-time, so not reached dead-code-elimination yet.
This problem was harder to debug than necessary. I was intent on blaming
the new table-driven passes structure, at least in part: the RTL passes
seemed hidden in some pass_expand structure iterated over, so I couldn't
"(gdb) up" from a SEGV or abort to see which specific pass that was
responsible. Looking closer, it seems this only happens for the initial
rtl pass (now called "expand") and rest_of_compilation each; the RTL
passes called from rest_of_compilation are ok. Never mind...
Still, verify_flow_info really should not be called before dumping
the initial RTL. In this case, a call-flow bug (rather, checking-bug)
meant there was no initial RTL dump to inspect. I think the
verify_flow_info call from tree_expand_cfg can be moved to the next pass
(right before its initialization), or to a pass *after* the initial RTL
expansion. BTW, the initial RTL dump file should be named 00.rtl, not
00.expand: there are no trees in there to excuse the name change. (That
might be unintended, but it doesn't seem like anybody has cared to make
that intention happen: there are no trees dumped there, so the name should
be changed back. I intend to do that. ;-)
Built and tested native i686-pc-linux-gnu (FC2) (no Ada) and the cross to
mmix-knuth-mmixware now completes building. As explained, I consider the
corrections to initialization and checking obvious, so committed as such.
* cfgrtl.c (rtl_verify_flow_info_1): When checking insns in a bb,
handle barriers in a bb by checking that it points to a NULL bb.
* emit-rtl.c (emit_barrier_before): Set BLOCK_FOR_INSN to NULL.
(emit_barrier_after, emit_barrier): Ditto.
Index: cfgrtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgrtl.c,v
retrieving revision 1.136
diff -p -c -r1.136 cfgrtl.c
*** cfgrtl.c 30 Sep 2004 21:25:44 -0000 1.136
--- cfgrtl.c 17 Oct 2004 21:22:48 -0000
*************** rtl_verify_flow_info_1 (void)
*** 2073,2079 ****
}
for (x = BB_HEAD (bb); x != NEXT_INSN (BB_END (bb)); x = NEXT_INSN (x))
! if (BLOCK_FOR_INSN (x) != bb)
{
debug_rtx (x);
if (! BLOCK_FOR_INSN (x))
--- 2073,2082 ----
}
for (x = BB_HEAD (bb); x != NEXT_INSN (BB_END (bb)); x = NEXT_INSN (x))
! /* We may have a barrier inside a basic block before dead code
! elimination. They always have a NULL BLOCK_FOR_INSN. */
! if (BLOCK_FOR_INSN (x) != bb
! && !(BARRIER_P (x) && BLOCK_FOR_INSN (x) == NULL))
{
debug_rtx (x);
if (! BLOCK_FOR_INSN (x))
Index: emit-rtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/emit-rtl.c,v
retrieving revision 1.419
diff -p -c -r1.419 emit-rtl.c
*** emit-rtl.c 8 Oct 2004 19:59:22 -0000 1.419
--- emit-rtl.c 17 Oct 2004 21:22:53 -0000
*************** emit_barrier_before (rtx before)
*** 4057,4062 ****
--- 4057,4063 ----
rtx insn = rtx_alloc (BARRIER);
INSN_UID (insn) = cur_insn_uid++;
+ BLOCK_FOR_INSN (insn) = NULL;
add_insn_before (insn, before);
return insn;
*************** emit_barrier_after (rtx after)
*** 4272,4277 ****
--- 4273,4279 ----
rtx insn = rtx_alloc (BARRIER);
INSN_UID (insn) = cur_insn_uid++;
+ BLOCK_FOR_INSN (insn) = NULL;
add_insn_after (insn, after);
return insn;
*************** emit_barrier (void)
*** 4668,4673 ****
--- 4670,4676 ----
{
rtx barrier = rtx_alloc (BARRIER);
INSN_UID (barrier) = cur_insn_uid++;
+ BLOCK_FOR_INSN (barrier) = NULL;
add_insn (barrier);
return barrier;
}
brgds, H-P