diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-02-02 19:28:57 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-02-02 19:28:57 +0000 |
commit | 0d179e03a9188621b28d235fa4f836af619e20c2 (patch) | |
tree | 6fde390bee19acf841e5ec6c02e403d195086099 /gcc/expr.c | |
parent | 0722b5c976b8844f5121fbfb820c517d24d50ab2 (diff) | |
download | gcc-0d179e03a9188621b28d235fa4f836af619e20c2.tar.gz |
* expr.c (expand_builtin_setjmp): Accept two new arguments for
the labels to branch to on first and subsequent executions. Don't
play with __dummy. Rename `setjmp' insn to `builtin_setjmp_setup',
and provide it with the jmp_buf. Use only one of
`builtin_setjmp_receiver' or `nonlocal_goto_receiver',
and provide the former with the target label.
(expand_builtin) [BUILTIN_SETJMP]: Generate a label for use by setjmp.
(expand_builtin) [BUILTIN_LONGJMP]: Split out to ...
(expand_builtin_longjmp): ... here. Recognize a `builtin_longjmp'
insn to replace all of the normal nonlocal_goto code. Don't play
with __dummy. Correct arguments to nonlocal_goto.
* expr.h (expand_builtin_setjmp): Update prototype.
* except.c (start_dynamic_handler): When using builtin_setjmp,
generate more accurate flow information.
* alpha.md (nonlocal_goto_receiver_osf): Delete.
(nonlocal_goto_receiver_vms): Rename to nonlocal_goto_receiver.
(builtin_longjmp, builtin_setjmp_receiver): New.
* sparc.md (update_return): Disambiguate unspec number.
(nonlocal_goto): Rearrange arguments to match caller in except.c.
(builtin_setjmp_setup): Rename from setjmp. Match and ignore the
jmp_buf operand.
* mips.md (nonlocal_goto_receiver, builtin_setjmp_receiver): Remove.
(builtin_setjmp_setup*, builtin_longjmp): New.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@17602 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/expr.c')
-rw-r--r-- | gcc/expr.c | 248 |
1 files changed, 124 insertions, 124 deletions
diff --git a/gcc/expr.c b/gcc/expr.c index af90d2447b6..4d927d73052 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -7613,20 +7613,16 @@ expand_builtin_return_addr (fndecl_code, count, tem) 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; @@ -7649,11 +7645,11 @@ expand_builtin_setjmp (buf_addr, target) machine-dependent. */ emit_move_insn (gen_rtx_MEM (Pmode, buf_addr), virtual_stack_vars_rtx); - emit_move_insn - (validize_mem (gen_rtx_MEM (Pmode, + emit_move_insn (validize_mem + (gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode)))), - gen_rtx_LABEL_REF (Pmode, lab1)); + gen_rtx_LABEL_REF (Pmode, lab1)); #ifdef HAVE_save_stack_nonlocal if (HAVE_save_stack_nonlocal) @@ -7665,19 +7661,23 @@ expand_builtin_setjmp (buf_addr, target) 2 * GET_MODE_SIZE (Pmode))); emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX); -#ifdef HAVE_setjmp - if (HAVE_setjmp) - emit_insn (gen_setjmp ()); + /* If there is further processing to do, do it. */ +#ifdef HAVE_builtin_setjmp_setup + if (HAVE_builtin_setjmp_setup) + emit_insn (gen_builtin_setjmp_setup (buf_addr)); #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); - /* Note that setjmp clobbers FP when we get here, so we have to make - sure it's marked as used by this function. */ + /* Tell flow about the strange goings on. */ + current_function_has_nonlocal_label = 1; + + /* Clobber the 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 @@ -7692,8 +7692,6 @@ expand_builtin_setjmp (buf_addr, target) #endif emit_move_insn (virtual_stack_vars_rtx, hard_frame_pointer_rtx); - current_function_has_nonlocal_label = 1; - #if ARG_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM if (fixed_regs[ARG_POINTER_REGNUM]) { @@ -7721,49 +7719,107 @@ expand_builtin_setjmp (buf_addr, target) } #endif +#ifdef HAVE_builtin_setjmp_receiver + if (HAVE_builtin_setjmp_receiver) + emit_insn (gen_builtin_setjmp_receiver (lab1)); + else +#endif #ifdef HAVE_nonlocal_goto_receiver - if (HAVE_nonlocal_goto_receiver) - emit_insn (gen_nonlocal_goto_receiver ()); + if (HAVE_nonlocal_goto_receiver) + emit_insn (gen_nonlocal_goto_receiver ()); + else #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); + ; /* Nothing */ + + /* Set TARGET, and branch to the next-time-through label. */ + emit_move_insn (target, gen_lowpart (GET_MODE (target), static_chain_rtx)); + emit_jump_insn (gen_jump (next_label)); + emit_barrier (); - /* 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); + return target; +} - 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); +void +expand_builtin_longjmp (buf_addr, value) + rtx buf_addr, value; +{ + rtx fp, lab, stack; + enum machine_mode sa_mode; -#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 +#ifdef POINTERS_EXTEND_UNSIGNED + buf_addr = convert_memory_address (Pmode, buf_addr); #endif + buf_addr = force_reg (Pmode, buf_addr); + + /* The value sent by longjmp is not allowed to be zero. Force it + to one if so. */ + if (GET_CODE (value) == CONST_INT) + { + if (INTVAL (value) == 0) + value = const1_rtx; + } + else + { + lab = gen_label_rtx (); + + emit_cmp_insn (value, const0_rtx, NE, NULL_RTX, GET_MODE (value), 0, 0); + emit_jump_insn (gen_bne (lab)); + emit_move_insn (value, const1_rtx); + emit_label (lab); + } + + /* Make sure the value is in the right mode to be copied to the chain. */ + if (GET_MODE (value) != VOIDmode) + value = gen_lowpart (GET_MODE (static_chain_rtx), value); + +#ifdef HAVE_builtin_longjmp + if (HAVE_builtin_longjmp) + { + /* Copy the "return value" to the static chain reg. */ + emit_move_insn (static_chain_rtx, value); + emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx)); + emit_insn (gen_builtin_longjmp (buf_addr)); + } + else #endif + { + fp = gen_rtx_MEM (Pmode, buf_addr); + lab = gen_rtx_MEM (Pmode, plus_constant (buf_addr, + GET_MODE_SIZE (Pmode))); -#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 +#ifdef HAVE_save_stack_nonlocal + sa_mode = (HAVE_save_stack_nonlocal + ? insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0] + : Pmode); +#else + sa_mode = Pmode; #endif - abort (); -#ifdef HAVE_builtin_setjmp_receiver - if (HAVE_builtin_setjmp_receiver) - emit_insn (gen_builtin_setjmp_receiver ()); + stack = gen_rtx_MEM (sa_mode, plus_constant (buf_addr, + 2 * GET_MODE_SIZE (Pmode))); + + /* 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 (value, fp, stack, lab)); + else #endif + { + lab = copy_to_reg (lab); - emit_move_insn (target, const1_rtx); - emit_label (lab2); - return target; + /* Copy the "return value" to the static chain reg. */ + emit_move_insn (static_chain_rtx, value); + + emit_move_insn (hard_frame_pointer_rtx, fp); + emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); + + 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); + } + } } @@ -8676,89 +8732,33 @@ expand_builtin (exp, target, subtarget, mode, ignore) if (arglist == 0 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE) break; + else + { + rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget, + VOIDmode, 0); + rtx lab = gen_label_rtx (); + rtx ret = expand_builtin_setjmp (buf_addr, target, lab, lab); + emit_label (lab); + return ret; + } - { - rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget, - VOIDmode, 0); - return expand_builtin_setjmp (buf_addr, target); - } - - /* __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, - convert_memory_address - (Pmode, - expand_expr (TREE_VALUE (arglist), - NULL_RTX, VOIDmode, 0))); -#else - rtx buf_addr - = force_reg (Pmode, expand_expr (TREE_VALUE (arglist), - NULL_RTX, - VOIDmode, 0)); -#endif - rtx fp = gen_rtx_MEM (Pmode, buf_addr); - rtx lab = gen_rtx_MEM (Pmode, - plus_constant (buf_addr, - GET_MODE_SIZE (Pmode))); - enum machine_mode sa_mode -#ifdef HAVE_save_stack_nonlocal - = (HAVE_save_stack_nonlocal - ? insn_operand_mode[(int) CODE_FOR_save_stack_nonlocal][0] - : Pmode); -#else - = Pmode; -#endif - rtx stack = gen_rtx_MEM (sa_mode, - 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 -#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); + rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget, + VOIDmode, 0); + rtx value = expand_expr (TREE_VALUE (TREE_CHAIN (arglist)), + const0_rtx, VOIDmode, 0); + expand_builtin_longjmp (buf_addr, value); + return const0_rtx; } - return const0_rtx; - } - /* Various hooks for the DWARF 2 __throw routine. */ case BUILT_IN_UNWIND_INIT: expand_builtin_unwind_init (); |