This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]