From: mrs Date: Wed, 7 May 1997 22:50:11 +0000 (+0000) Subject: * except.c (start_dynamic_handler): Fix so that we can use X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=177858580b6dc2bd20fd3fc6689c5c4aa2e2d488 * except.c (start_dynamic_handler): Fix so that we can use __builtin_setjmp, and default to using __builtin_setjmp instead of setjmp. * expr.c (expand_builtin_setjmp): New routine, split out from existing inline code from expand_builtin. (expand_builtin): Split out code into expand_builtin_setjmp. * expr.h (expand_builtin_setjmp): Add declaration. * libgcc2.c (__sjthrow): Default to using __builtin_setjmp instead of setjmp. (__sjpopnthrow): Likewise. * optabs.c (init_optabs): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@14045 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/except.c b/gcc/except.c index 71925a575b1..91afbc3052b 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -693,9 +693,9 @@ add_partial_entry (handler) when there are no more elements in the dynamic handler chain, when the value is &top_elt from libgcc2.c. Immediately after the pointer, is an area suitable for setjmp/longjmp when - USE_BUILTIN_SETJMP isn't defined, and an area suitable for - __builtin_setjmp/__builtin_longjmp when USE_BUILTIN_SETJMP is - defined. + DONT_USE_BUILTIN_SETJMP is defined, and an area suitable for + __builtin_setjmp/__builtin_longjmp when DONT_USE_BUILTIN_SETJMP + isn't defined. This routine is here to facilitate the porting of this code to systems with threads. One can either replace the routine we emit a @@ -843,10 +843,10 @@ static void start_dynamic_handler () { rtx dhc, dcc; - rtx x, arg; + rtx x, arg, buf; int size; -#ifdef USE_BUILTIN_SETJMP +#ifndef DONT_USE_BUILTIN_SETJMP /* The number of Pmode words for the setjmp buffer, when using the builtin setjmp/longjmp, see expand_builtin, case BUILT_IN_LONGJMP. */ @@ -882,10 +882,14 @@ start_dynamic_handler () emit_move_insn (dcc, const0_rtx); /* The jmpbuf starts two words into the area allocated. */ + buf = plus_constant (XEXP (arg, 0), GET_MODE_SIZE (Pmode)*2); +#ifdef DONT_USE_BUILTIN_SETJMP x = emit_library_call_value (setjmp_libfunc, NULL_RTX, 1, SImode, 1, - plus_constant (XEXP (arg, 0), GET_MODE_SIZE (Pmode)*2), - Pmode); + buf, Pmode); +#else + x = expand_builtin_setjmp (buf, NULL_RTX); +#endif /* If we come back here for a catch, transfer control to the handler. */ diff --git a/gcc/expr.c b/gcc/expr.c index 1dc79b67d38..4e3c981682b 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -7880,6 +7880,169 @@ expand_builtin_return_addr (fndecl_code, count, tem) #endif return tem; } + +/* __builtin_setjmp is passed a pointer to an array of five words (not + all will be used on all machines). It operates similarly to the C + library function of the same name, but is more efficient. Much of + the code below (and for longjmp) is copied from the handling of + non-local gotos. + + NOTE: This is intended for use by GNAT and the exception handling + scheme in the compiler and will only work in the method used by + them. */ + +rtx +expand_builtin_setjmp (buf_addr, target) + rtx buf_addr; + rtx target; +{ + rtx lab1 = gen_label_rtx (), lab2 = 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; + + value_mode = TYPE_MODE (integer_type_node); + +#ifdef POINTERS_EXTEND_UNSIGNED + buf_addr = convert_memory_address (Pmode, buf_addr); +#endif + + buf_addr = force_reg (Pmode, buf_addr); + + if (target == 0 || GET_CODE (target) != REG + || REGNO (target) < FIRST_PSEUDO_REGISTER) + target = gen_reg_rtx (value_mode); + + emit_queue (); + + CONST_CALL_P (emit_note (NULL_PTR, NOTE_INSN_SETJMP)) = 1; + current_function_calls_setjmp = 1; + + /* We store the frame pointer and the address of lab1 in the buffer + and use the rest of it for the stack save area, which is + machine-dependent. */ + emit_move_insn (gen_rtx (MEM, Pmode, buf_addr), + virtual_stack_vars_rtx); + emit_move_insn + (validize_mem (gen_rtx (MEM, Pmode, + plus_constant (buf_addr, + GET_MODE_SIZE (Pmode)))), + gen_rtx (LABEL_REF, Pmode, lab1)); + +#ifdef HAVE_save_stack_nonlocal + if (HAVE_save_stack_nonlocal) + sa_mode = insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0]; +#endif + + stack_save = gen_rtx (MEM, sa_mode, + plus_constant (buf_addr, + 2 * GET_MODE_SIZE (Pmode))); + emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX); + +#ifdef HAVE_setjmp + if (HAVE_setjmp) + emit_insn (gen_setjmp ()); +#endif + + /* Set TARGET to zero and branch around the other case. */ + emit_move_insn (target, const0_rtx); + emit_jump_insn (gen_jump (lab2)); + emit_barrier (); + emit_label (lab1); + + /* Note that setjmp clobbers FP when we get here, so we have to make + sure it's marked as used by this function. */ + emit_insn (gen_rtx (USE, VOIDmode, hard_frame_pointer_rtx)); + + /* Mark the static chain as clobbered here so life information + doesn't get messed up for it. */ + emit_insn (gen_rtx (CLOBBER, VOIDmode, static_chain_rtx)); + + /* Now put in the code to restore the frame pointer, and argument + pointer, if needed. The code below is from expand_end_bindings + in stmt.c; see detailed documentation there. */ +#ifdef HAVE_nonlocal_goto + if (! HAVE_nonlocal_goto) +#endif + emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx); + + current_function_has_nonlocal_goto = 1; + +#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM + if (fixed_regs[ARG_POINTER_REGNUM]) + { +#ifdef ELIMINABLE_REGS + static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS; + + for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++) + if (elim_regs[i].from == ARG_POINTER_REGNUM + && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM) + break; + + if (i == sizeof elim_regs / sizeof elim_regs [0]) +#endif + { + /* Now restore our arg pointer from the address at which it + was saved in our stack frame. + If there hasn't be space allocated for it yet, make + some now. */ + if (arg_pointer_save_area == 0) + arg_pointer_save_area + = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0); + emit_move_insn (virtual_incoming_args_rtx, + copy_to_reg (arg_pointer_save_area)); + } + } +#endif + +#ifdef HAVE_nonlocal_goto_receiver + 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); + return target; +} + /* Expand an expression EXP that calls a built-in function, with result going to TARGET if that's convenient @@ -8718,15 +8881,6 @@ expand_builtin (exp, target, subtarget, mode, ignore) break; #endif - /* __builtin_setjmp is passed a pointer to an array of five words - (not all will be used on all machines). It operates similarly to - the C library function of the same name, but is more efficient. - Much of the code below (and for longjmp) is copied from the handling - of non-local gotos. - - NOTE: This is intended for use by GNAT and will only work in - the method used by it. This code will likely NOT survive to - the GCC 2.8.0 release. */ case BUILT_IN_SETJMP: if (arglist == 0 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE) @@ -8735,148 +8889,7 @@ expand_builtin (exp, target, subtarget, mode, ignore) { rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0); - rtx lab1 = gen_label_rtx (), lab2 = gen_label_rtx (); - enum machine_mode sa_mode = Pmode; - 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; - int i; - -#ifdef POINTERS_EXTEND_UNSIGNED - buf_addr = convert_memory_address (Pmode, buf_addr); -#endif - - buf_addr = force_reg (Pmode, buf_addr); - - if (target == 0 || GET_CODE (target) != REG - || REGNO (target) < FIRST_PSEUDO_REGISTER) - target = gen_reg_rtx (value_mode); - - emit_queue (); - - CONST_CALL_P (emit_note (NULL_PTR, NOTE_INSN_SETJMP)) = 1; - current_function_calls_setjmp = 1; - - /* We store the frame pointer and the address of lab1 in the buffer - and use the rest of it for the stack save area, which is - machine-dependent. */ - emit_move_insn (gen_rtx (MEM, Pmode, buf_addr), - virtual_stack_vars_rtx); - emit_move_insn - (validize_mem (gen_rtx (MEM, Pmode, - plus_constant (buf_addr, - GET_MODE_SIZE (Pmode)))), - gen_rtx (LABEL_REF, Pmode, lab1)); - -#ifdef HAVE_save_stack_nonlocal - if (HAVE_save_stack_nonlocal) - sa_mode = insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0]; -#endif - - stack_save = gen_rtx (MEM, sa_mode, - plus_constant (buf_addr, - 2 * GET_MODE_SIZE (Pmode))); - emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX); - -#ifdef HAVE_setjmp - if (HAVE_setjmp) - emit_insn (gen_setjmp ()); -#endif - - /* Set TARGET to zero and branch around the other case. */ - emit_move_insn (target, const0_rtx); - emit_jump_insn (gen_jump (lab2)); - emit_barrier (); - emit_label (lab1); - - /* Note that setjmp clobbers FP when we get here, so we have to - make sure it's marked as used by this function. */ - emit_insn (gen_rtx (USE, VOIDmode, hard_frame_pointer_rtx)); - - /* Mark the static chain as clobbered here so life information - doesn't get messed up for it. */ - emit_insn (gen_rtx (CLOBBER, VOIDmode, static_chain_rtx)); - - /* Now put in the code to restore the frame pointer, and argument - pointer, if needed. The code below is from expand_end_bindings - in stmt.c; see detailed documentation there. */ -#ifdef HAVE_nonlocal_goto - if (! HAVE_nonlocal_goto) -#endif - emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx); - - current_function_has_nonlocal_goto = 1; - -#if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM - if (fixed_regs[ARG_POINTER_REGNUM]) - { -#ifdef ELIMINABLE_REGS - static struct elims {int from, to;} elim_regs[] = ELIMINABLE_REGS; - - for (i = 0; i < sizeof elim_regs / sizeof elim_regs[0]; i++) - if (elim_regs[i].from == ARG_POINTER_REGNUM - && elim_regs[i].to == HARD_FRAME_POINTER_REGNUM) - break; - - if (i == sizeof elim_regs / sizeof elim_regs [0]) -#endif - { - /* Now restore our arg pointer from the address at which it - was saved in our stack frame. - If there hasn't be space allocated for it yet, make - some now. */ - if (arg_pointer_save_area == 0) - arg_pointer_save_area - = assign_stack_local (Pmode, GET_MODE_SIZE (Pmode), 0); - emit_move_insn (virtual_incoming_args_rtx, - copy_to_reg (arg_pointer_save_area)); - } - } -#endif - -#ifdef HAVE_nonlocal_goto_receiver - 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); - return target; + return expand_builtin_setjmp (buf_addr, target); } /* __builtin_longjmp is passed a pointer to an array of five words diff --git a/gcc/expr.h b/gcc/expr.h index ee954ef43b7..bb957b75f12 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -685,6 +685,8 @@ extern rtx store_expr PROTO((tree, rtx, int)); 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)); + #ifdef TREE_CODE /* Generate code for computing expression EXP. An rtx for the computed value is returned. The value is never null. diff --git a/gcc/libgcc2.c b/gcc/libgcc2.c index 107c4bf04df..09b6a15dcc6 100644 --- a/gcc/libgcc2.c +++ b/gcc/libgcc2.c @@ -3120,7 +3120,7 @@ __terminate () is raised when using the setjmp/longjmp exception handling codegen method. */ -extern longjmp (void *, int); +extern void longjmp (void *, int); extern void *__eh_type; @@ -3169,7 +3169,11 @@ __sjthrow () buf[0] = (*dhc); /* try { */ +#ifdef DONT_USE_BUILTIN_SETJMP if (! setjmp (&buf[2])) +#else + if (! __builtin_setjmp (&buf[2])) +#endif { *dhc = buf; while (cleanup[0]) @@ -3206,10 +3210,10 @@ __sjthrow () /* And then we jump to the handler. */ -#ifdef USE_BUILTIN_SETJMP - __builtin_longjmp (jmpbuf, 1); -#else +#ifdef DONT_USE_BUILTIN_SETJMP longjmp (jmpbuf, 1); +#else + __builtin_longjmp (jmpbuf, 1); #endif } @@ -3240,7 +3244,11 @@ __sjpopnthrow () buf[0] = (*dhc); /* try { */ +#ifdef DONT_USE_BUILTIN_SETJMP if (! setjmp (&buf[2])) +#else + if (! __builtin_setjmp (&buf[2])) +#endif { *dhc = buf; while (cleanup[0]) diff --git a/gcc/optabs.c b/gcc/optabs.c index b93a383bb6a..992660d0c87 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -4277,7 +4277,7 @@ init_optabs () sjthrow_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__sjthrow"); sjpopnthrow_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__sjpopnthrow"); terminate_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__terminate"); -#ifdef USE_BUILTIN_SETJMP +#ifndef DONT_USE_BUILTIN_SETJMP setjmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__builtin_setjmp"); longjmp_libfunc = gen_rtx (SYMBOL_REF, Pmode, "__builtin_longjmp"); #else