EH clobbered by longjmp again
Richard Henderson
rth@cygnus.com
Fri Sep 5 00:21:00 GMT 1997
It seems to me that flow has not been taught that the builtin
setjmp uses the non-local goto support, saving everything to
the stack at appropriate places, and therefore cannot have
things clobbered out from underneath it.
BTW: is there no code in gcc to do basic block reordering? Is
this just something that has never come up?
I fixed things up so that the sjlj exception handling would no
longer test a "return value", but rather jump directly to the
appropriate labels (same warning message btw). And I wind up
with code that looks like
Basic block 0: first insn 11, last 101.
Reached from blocks:
Registers live at start: 15 30 63
Basic block 1: first insn 103, last 109.
Reached from blocks: previous
Registers live at start: 15 30 63 69 85
Basic block 2: first insn 111, last 155.
Reached from blocks: 0
Registers live at start: 15 30 63 68 69 101
Basic block 3: first insn 159, last 172.
Reached from blocks: 1
Registers live at start: 15 30 63 69 85
Basic block 4: first insn 174, last 180.
Reached from blocks: previous
Registers live at start: 15 30 63
Basic block 5: first insn 182, last 242.
Reached from blocks: 3
Registers live at start: 30 63 69 131
Basic block 6: first insn 244, last 245.
Reached from blocks: 4
Registers live at start: 30
Basic block 7: first insn 248, last 323.
Reached from blocks: 2
Registers live at start: 15 30 63 68
Basic block 8: first insn 277, last 274.
Reached from blocks: 8 previous
Registers live at start: 15 30 63 68
Basic block 9: first insn 297, last 317.
Reached from blocks: 7 previous
Registers live at start: 15 30 63
(Back to the warning problem for a moment, note that it is reg 68 in
block 7 that flow is complaining about, but that it knows that control
cannot go from the catches back into 7, 8 or 9.)
It seems like it should be rather easy to rearrange things such
that block-pairs that have such a one-to-one relationship are
placed ajacent to one another so that the unconditional jump can
be avoided.
It would also be nice to have such a reorganizer so that it can
take information from the branch predictor and move seldomly used
blocks out of the way so that the normal path just drops through.
And for targets like Alpha that have static branch prediction, it
would been nice to be able to lay things out as best we can.
If anyone is curious, the patch I used is appended.
It also does as Jim suggested this evening (and I've thought ought
to be done for a while), which is to get rid of that stupid __dummy()
call. I fixed things up for Alpha, but I don't know how to make the
MIPS assembler do the right thing.
r~
Index: except.c
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/except.c,v
retrieving revision 1.2
diff -u -p -r1.2 except.c
--- except.c 1997/09/03 02:08:35 1.2
+++ except.c 1997/09/05 06:55:15
@@ -881,14 +881,17 @@ start_dynamic_handler ()
#ifdef DONT_USE_BUILTIN_SETJMP
x = emit_library_call_value (setjmp_libfunc, NULL_RTX, 1, SImode, 1,
buf, Pmode);
+ /* If we come back here for a catch, transfer control to the handler. */
+ jumpif_rtx (x, ehstack.top->entry->exception_handler_label);
#else
- x = expand_builtin_setjmp (buf, NULL_RTX);
+ {
+ /* A label to continue execution for the no exception case. */
+ rtx noex = gen_label_rtx();
+ x = expand_builtin_setjmp (buf, NULL_RTX, noex,
+ ehstack.top->entry->exception_handler_label);
+ emit_label(noex);
+ }
#endif
-
- /* If we come back here for a catch, transfer control to the
- handler. */
-
- jumpif_rtx (x, ehstack.top->entry->exception_handler_label);
/* We are committed to this, so update the handler chain. */
Index: expr.c
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/expr.c,v
retrieving revision 1.3
diff -u -p -r1.3 expr.c
--- expr.c 1997/09/03 05:33:06 1.3
+++ expr.c 1997/09/05 06:55:16
@@ -8048,20 +8048,16 @@ expand_builtin_return_addr (fndecl_code,
them. */
rtx
-expand_builtin_setjmp (buf_addr, target)
+expand_builtin_setjmp (buf_addr, target, first_label, next_label)
rtx buf_addr;
rtx target;
+ rtx first_label, next_label;
{
- rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx ();
+ rtx lab1 = gen_label_rtx ();
enum machine_mode sa_mode = Pmode, value_mode;
rtx stack_save;
int old_inhibit_defer_pop = inhibit_defer_pop;
- int return_pops
- = RETURN_POPS_ARGS (get_identifier ("__dummy"),
- build_function_type (void_type_node, NULL_TREE),
- 0);
rtx next_arg_reg;
- CUMULATIVE_ARGS args_so_far;
rtx op0;
int i;
@@ -8108,9 +8104,9 @@ expand_builtin_setjmp (buf_addr, target)
emit_insn (gen_setjmp ());
#endif
- /* Set TARGET to zero and branch around the other case. */
+ /* Set TARGET to zero and branch to the first-time-through label */
emit_move_insn (target, const0_rtx);
- emit_jump_insn (gen_jump (lab2));
+ emit_jump_insn (gen_jump (first_label));
emit_barrier ();
emit_label (lab1);
@@ -8168,39 +8164,13 @@ expand_builtin_setjmp (buf_addr, target)
if (HAVE_nonlocal_goto_receiver)
emit_insn (gen_nonlocal_goto_receiver ());
#endif
- /* The static chain pointer contains the address of dummy function.
- We need to call it here to handle some PIC cases of restoring a
- global pointer. Then return 1. */
- op0 = copy_to_mode_reg (Pmode, static_chain_rtx);
-
- /* We can't actually call emit_library_call here, so do everything
- it does, which isn't much for a libfunc with no args. */
- op0 = memory_address (FUNCTION_MODE, op0);
-
- INIT_CUMULATIVE_ARGS (args_so_far, NULL_TREE,
- gen_rtx (SYMBOL_REF, Pmode, "__dummy"), 1);
- next_arg_reg = FUNCTION_ARG (args_so_far, VOIDmode, void_type_node, 1);
-
-#ifndef ACCUMULATE_OUTGOING_ARGS
-#ifdef HAVE_call_pop
- if (HAVE_call_pop)
- emit_call_insn (gen_call_pop (gen_rtx (MEM, FUNCTION_MODE, op0),
- const0_rtx, next_arg_reg,
- GEN_INT (return_pops)));
- else
-#endif
-#endif
-
-#ifdef HAVE_call
- if (HAVE_call)
- emit_call_insn (gen_call (gen_rtx (MEM, FUNCTION_MODE, op0),
- const0_rtx, next_arg_reg, const0_rtx));
- else
-#endif
- abort ();
emit_move_insn (target, const1_rtx);
- emit_label (lab2);
+
+ /* And finally jump to the next-time-through label. */
+ emit_jump_insn (gen_jump (next_label));
+ emit_barrier ();
+
return target;
}
@@ -9059,21 +9029,19 @@ expand_builtin (exp, target, subtarget,
{
rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget,
VOIDmode, 0);
- return expand_builtin_setjmp (buf_addr, target);
+ rtx lab = gen_label_rtx ();
+ return expand_builtin_setjmp (buf_addr, target, lab, lab);
}
- /* __builtin_longjmp is passed a pointer to an array of five words
- and a value, which is a dummy. It's similar to the C library longjmp
- function but works with __builtin_setjmp above. */
+ /* __builtin_longjmp is passed a pointer to an array of five words.
+ It's similar to the C library longjmp function but works with
+ __builtin_setjmp above. */
case BUILT_IN_LONGJMP:
if (arglist == 0 || TREE_CHAIN (arglist) == 0
|| TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE)
break;
{
- tree dummy_id = get_identifier ("__dummy");
- tree dummy_type = build_function_type (void_type_node, NULL_TREE);
- tree dummy_decl = build_decl (FUNCTION_DECL, dummy_id, dummy_type);
#ifdef POINTERS_EXTEND_UNSIGNED
rtx buf_addr
= force_reg (Pmode,
@@ -9102,35 +9070,25 @@ expand_builtin (exp, target, subtarget,
plus_constant (buf_addr,
2 * GET_MODE_SIZE (Pmode)));
- DECL_EXTERNAL (dummy_decl) = 1;
- TREE_PUBLIC (dummy_decl) = 1;
- make_decl_rtl (dummy_decl, NULL_PTR, 1);
-
/* Expand the second expression just for side-effects. */
expand_expr (TREE_VALUE (TREE_CHAIN (arglist)),
const0_rtx, VOIDmode, 0);
- assemble_external (dummy_decl);
-
/* Pick up FP, label, and SP from the block and jump. This code is
from expand_goto in stmt.c; see there for detailed comments. */
#if HAVE_nonlocal_goto
if (HAVE_nonlocal_goto)
emit_insn (gen_nonlocal_goto (fp, lab, stack,
XEXP (DECL_RTL (dummy_decl), 0)));
- else
+ else
#endif
{
lab = copy_to_reg (lab);
emit_move_insn (hard_frame_pointer_rtx, fp);
emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
- /* Put in the static chain register the address of the dummy
- function. */
- emit_move_insn (static_chain_rtx, XEXP (DECL_RTL (dummy_decl), 0));
emit_insn (gen_rtx (USE, VOIDmode, hard_frame_pointer_rtx));
emit_insn (gen_rtx (USE, VOIDmode, stack_pointer_rtx));
- emit_insn (gen_rtx (USE, VOIDmode, static_chain_rtx));
emit_indirect_jump (lab);
}
Index: expr.h
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/expr.h,v
retrieving revision 1.4
diff -u -p -r1.4 expr.h
--- expr.h 1997/08/29 15:02:03 1.4
+++ expr.h 1997/09/05 06:55:16
@@ -750,7 +750,7 @@ extern rtx store_expr PROTO((tree, rtx,
Useful after calling expand_expr with 1 as sum_ok. */
extern rtx force_operand PROTO((rtx, rtx));
-extern rtx expand_builtin_setjmp PROTO((rtx, rtx));
+extern rtx expand_builtin_setjmp PROTO((rtx, rtx, rtx, rtx));
#ifdef TREE_CODE
/* Generate code for computing expression EXP.
Index: config/alpha/alpha.md
===================================================================
RCS file: /cvs/cvsfiles/egcs/gcc/config/alpha/alpha.md,v
retrieving revision 1.3
diff -u -p -r1.3 alpha.md
--- alpha.md 1997/09/03 01:27:01 1.3
+++ alpha.md 1997/09/05 06:55:18
@@ -4451,15 +4451,32 @@
(define_insn "exception_receiver"
[(unspec_volatile [(const_int 0)] 2)]
"! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT"
- ".long 0xc3a00000\;ldgp $29,0($29)")
+ "br $29,.+4\;ldgp $29,0($29)")
-(define_expand "nonlocal_goto_receiver"
+(define_insn "nonlocal_goto_receiver_osf"
+ [(unspec_volatile [(const_int 0)] 2)]
+ ""
+ "br $29,.+4\;ldgp $29,0($29)")
+
+(define_expand "nonlocal_goto_receiver_vms"
[(unspec_volatile [(const_int 0)] 1)
(set (reg:DI 27) (mem:DI (reg:DI 29)))
(unspec_volatile [(const_int 0)] 1)
(use (reg:DI 27))]
- "TARGET_OPEN_VMS"
+ ""
"")
+
+(define_expand "nonlocal_goto_receiver"
+ [(unspec_volatile [(const_int 0)] 2)]
+ "! TARGET_WINDOWS_NT"
+ "
+{
+ if (TARGET_OPEN_VMS)
+ emit_insn (gen_nonlocal_goto_receiver_vms ());
+ else
+ emit_insn (gen_nonlocal_goto_receiver_osf ());
+ DONE;
+}")
(define_insn "arg_home"
[(unspec [(const_int 0)] 0)
More information about the Gcc
mailing list