This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
EH flow analysis
- To: wilson at cygnus dot com (Jim Wilson)
- Subject: EH flow analysis
- From: Jason Merrill <jason at cygnus dot com>
- Date: 23 Sep 1997 09:05:07 -0700
- Cc: egcs at cygnus dot com
- References: <199708300032.RAA14187.cygnus.egcs.bugs@cygnus.com>
>>>>> Jim Wilson <wilson@cygnus.com> writes:
> Without the sjlj exceptions, there is no indirect jump, but there is a
> list of exception handler labels, and each block that starts with an
> exception handler label is marked as live. However, we are still missing
> control flow info here, because we don't know how these exception handler
> labels are reached. flow notices that it has unreachable blocks which
> are marked as reachable, so it just adds a bogus connection to the
> previous block. Since the bogus connections all go one way, backwards,
> it is impossible (or at least very unlikely) to get a a circular group of
> unreachable blocks. But while it happens to work, the flow info is still
> wrong, and this will have to be fixed before it causes problems. This
> probably needs to be fixed the same way as I mentioned above, i.e. flow
> should know that exception handler regions are reachable from all call
> instructions (or all call instructions in scope).
Yep. Here's a testcase that breaks with -fno-sjlj-exceptions:
struct A {
int i;
~A ();
A () : i (0) {}
};
struct B : public A {
B(): A() {}
};
struct C {
int i;
B b[1];
};
C c;
Mike's earlier patch fixes the flow information, but flow still doesn't
delete all unreachable handlers. Another jump (and exception_optimize)
pass will delete the rest, but that doesn't happen again until the very end
of compilation, when we've already aborted because we saw a use of a dead
pseudo.
Here's a patch that fixes this test case in a pessimistic way, by assuming
for the purposes of flow analysis that all handlers are reachable from all
calls. A better solution will be to only note that the innermost handler
is reachable, and make flow delete all unreachable code; then we can do
away with exception_optimize.
Tue Sep 23 09:01:38 1997 Jason Merrill <jason@yorick.cygnus.com>
* flow.c (find_basic_blocks): Mark calls as potentially jumping
to the EH labels.
Index: flow.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gcc/flow.c,v
retrieving revision 1.89
diff -c -r1.89 flow.c
*** flow.c 1997/09/22 01:41:20 1.89
--- flow.c 1997/09/23 16:00:03
***************
*** 467,474 ****
if (! LABEL_REF_NONLOCAL_P (x))
block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
! for (x = exception_handler_labels; x; x = XEXP (x, 1))
! block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
/* Record which basic blocks control can drop in to. */
--- 467,475 ----
if (! LABEL_REF_NONLOCAL_P (x))
block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
! if (asynchronous_exceptions)
! for (x = exception_handler_labels; x; x = XEXP (x, 1))
! block_live[BLOCK_NUM (XEXP (x, 0))] = 1;
/* Record which basic blocks control can drop in to. */
***************
*** 532,537 ****
--- 533,543 ----
for (x = nonlocal_label_list; x; x = XEXP (x, 1))
mark_label_ref (gen_rtx (LABEL_REF, VOIDmode, XEXP (x, 0)),
insn, 0);
+
+ if (! asynchronous_exceptions)
+ for (x = exception_handler_labels; x; x = XEXP (x, 1))
+ mark_label_ref (gen_rtx (LABEL_REF, VOIDmode, XEXP (x, 0)),
+ insn, 0);
/* ??? This could be made smarter:
in some cases it's possible to tell that certain