PATCH: sjlj exceptions
John David Anglin
Fri Oct 27 13:21:00 GMT 2000
This patch resolves to some extent the problems noted in these two postings:
< http://gcc.gnu.org/ml/gcc-bugs/2000-08/msg00687.html > and
< http://gcc.gnu.org/ml/gcc-bugs/2000-10/msg00083.html >. My investigation
revealed that the problem is only present when sjlj exceptions are used.
The memory expansion occured in the gcse pass and was a result of the
large number of edges present in functions using sjlj exceptions.
There are two separate parts to the fix. The first part is to define
a nonlocal goto label after the setjmp call when a library version of
setjmp. This fixes the basic block reordering problem noted in this post:
< http://gcc.gnu.org/ml/gcc-bugs/2000-10/msg00526.html >.
The second part is to set current_function_calls_setjmp = 1. This causes
the gcse pass to punt, preventing the memory buildup. I think it is also
necessary to ensure that registers are properly saved. It also causes
all the NOTE_INSN_EH_REGION_[BEG,END] notes to be deleted after the first
The patch has been tested with a complete bootstrap and check.
DONT_USE_BUILTIN_SETJMP was not defined for this test. The tFile.exp
test now completes in a reasonable 196 seconds on a 735. There are no gcc
regressions. Here are the results of the g++ testsuite.
FAIL: g++.eh/crash4.C caused compiler crash
FAIL: g++.ext/attrib5.C (test for excess errors)
FAIL: g++.ext/instantiate1.C not instantiated (test for errors, line 18)
FAIL: g++.ext/instantiate1.C not instantiated (test for errors, line 20)
FAIL: g++.ext/instantiate2.C not instantiated (test for errors, line 16)
FAIL: g++.ext/instantiate3.C not instantiated (test for errors, line 13)
XPASS: g++.mike/eh33.C (test for excess errors)
XPASS: g++.mike/eh33.C Execution test
XPASS: g++.mike/eh50.C (test for excess errors)
XPASS: g++.mike/eh50.C Execution test
FAIL: g++.other/crash18.C (test for excess errors)
XPASS: g++.pt/static3.C (test for excess errors)
XPASS: g++.pt/static3.C Execution test
XPASS: g++.pt/static6.C (test for excess errors)
Thus, all is ok with g++ testsuite.
1) The gcse pass no longer runs when sjlj exceptions are used. It
may be possible to run the gcse pass when using sjlj exceptions but
I think make_edges needs improvement first. Given this, should
sjlj still be the default exception mode? On the otherhand, I
doubt -fno-sjlj-exceptions has ever been tested on the pa.
2) The memory used by the gcse pass is very dependent on the number
of edges created by make_edges. I think make_edges has to try
harder to determine the active handler for call insns and aynchronous
exceptions (see code and notes following line 1157 in flow.c).
Currently, calls without a REG_EH_REGION note generate edges to
all nonlocal labels in the function. The function t7 in tFile.cc
has about 60 nonlocal goto labels on the pa and it is not a very
big function. The gcse pass needed about 40MB peak to handle this.
3) There may be an issue regarding inlining. According to
function_cannot_inline_p, functions with current_function_calls_setjmp
!= 0 are not safe to integrate into other functions. Thus, using
sjlj-exceptions may limit inlining. On the otherhand, I don't
think the above restriction is being adhered to.
4) I suspect that expand_calls needs to be modified to add a nonlocal
goto label after "real" setjmp calls to avoid the basic block
reordering problem noted above. This problem may only occur
when the are multiple setjmp calls.
J. David Anglin firstname.lastname@example.org
National Research Council of Canada (613) 990-0752 (FAX: 952-6605)
2000-10-26 J. David Anglin <email@example.com>
* libgcc2.c: Don't provide an explicit prototype for longjmp since
this may clash with a previously included one.
* except.c (start_dynamic_handler): Add a nonlocal goto label after
library setjmp calls so flow doesn't get confused and set
current_function_calls_setjmp = 1 because gcse can't build an
accurate cfg in functions which call setjmp.
--- libgcc2.c.orig Sat Oct 21 14:00:41 2000
+++ libgcc2.c Wed Oct 25 19:17:12 2000
@@ -3438,7 +3438,7 @@
-extern void longjmp (void *, int);
+extern void longjmp ();
/* Routine to get the head of the current thread's dynamic handler chain
--- except.c.orig Fri Oct 13 15:58:55 2000
+++ except.c Thu Oct 26 19:50:34 2000
@@ -1351,9 +1351,15 @@
buf = plus_constant (XEXP (arg, 0), GET_MODE_SIZE (Pmode)*2);
+ /* Generate a nonlocal goto label so flow doesn't get confused. */
+ rtx lab1 = gen_label_rtx();
x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_CONST,
TYPE_MODE (integer_type_node), 1,
+ emit_label (lab1);
+ current_function_has_nonlocal_label = 1;
+ = gen_rtx_EXPR_LIST (VOIDmode, lab1, nonlocal_goto_handler_labels);
/* If we come back here for a catch, transfer control to the handler. */
jumpif_rtx (x, ehstack.top->entry->exception_handler_label);
@@ -1366,6 +1372,9 @@
+ /* Tell the world that this function calls setjmp. */
+ current_function_calls_setjmp = 1;
/* We are committed to this, so update the handler chain. */
emit_move_insn (dhc, force_operand (XEXP (arg, 0), NULL_RTX));
More information about the Gcc-bugs