From 6fd1c67b8b4b139397e122ed9440da75fdab277c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 2 Feb 1998 11:28:57 -0800 Subject: [PATCH] expr.c (expand_builtin_setjmp): Accept two new arguments for the labels to branch to on first and subsequent... * 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. From-SVN: r17602 --- gcc/ChangeLog | 27 +++++ gcc/config/alpha/alpha.md | 47 +++++--- gcc/config/mips/mips.md | 73 +++++++---- gcc/config/sparc/sparc.md | 44 ++++--- gcc/except.c | 15 ++- gcc/expr.c | 248 +++++++++++++++++++------------------- gcc/expr.h | 2 +- 7 files changed, 265 insertions(+), 191 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f54e31ee091..3c23a831467 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,30 @@ +Mon Feb 2 19:18:14 1998 Richard Henderson + + * 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. + Mon Feb 2 16:43:10 1998 John Carr * mips.md: Change gen_rtx (CONST_INT) to GEN_INT. diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md index 44f9cb95876..b1cbc3bcbfd 100644 --- a/gcc/config/alpha/alpha.md +++ b/gcc/config/alpha/alpha.md @@ -5050,15 +5050,36 @@ } }") -;; Ideally we should be able to define nonlocal_goto and arrange -;; for the pc to be in a known place. Or perhaps branch back via -;; br instead of jmp. -(define_insn "nonlocal_goto_receiver_osf" - [(unspec_volatile [(const_int 0)] 2)] +(define_expand "builtin_longjmp" + [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)] "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT" - "br $29,$LGOTO%=\\n$LGOTO%=:\;ldgp $29,0($29)") + " +{ + /* The elements of the buffer are, in order: */ + rtx fp = gen_rtx_MEM (Pmode, operands[0]); + rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 8)); + rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 16)); + rtx pv = gen_rtx_REG (Pmode, 27); + + /* This bit is the same as expand_builtin_longjmp. */ + emit_move_insn (hard_frame_pointer_rtx, fp); + emit_move_insn (pv, lab); + 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)); + + /* Load the label we are jumping through into $27 so that we know + where to look for it when we get back to setjmp's function for + restoring the gp. */ + emit_indirect_jump (pv); +}") -(define_expand "nonlocal_goto_receiver_vms" +(define_insn "builtin_setjmp_receiver" + [(unspec_volatile [(match_operand 0 "" "")] 2)] + "! TARGET_OPEN_VMS && ! TARGET_WINDOWS_NT" + "\\n$LSJ%=:\;ldgp $29,$LSJ%=-%l0($27)") + +(define_expand "nonlocal_goto_receiver" [(unspec_volatile [(const_int 0)] 1) (set (reg:DI 27) (mem:DI (reg:DI 29))) (unspec_volatile [(const_int 0)] 1) @@ -5066,18 +5087,6 @@ "TARGET_OPEN_VMS" "") -(define_expand "nonlocal_goto_receiver" - [(unspec_volatile [(const_int 0)] 2)] - "" - " -{ - if (TARGET_OPEN_VMS) - emit_insn(gen_nonlocal_goto_receiver_vms ()); - else if (!TARGET_WINDOWS_NT) - emit_insn(gen_nonlocal_goto_receiver_osf ()); - DONE; -}") - (define_insn "arg_home" [(unspec [(const_int 0)] 0) (use (reg:DI 1)) diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index eaf80efacb9..10c0bfe261b 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -8820,35 +8820,64 @@ move\\t%0,%z4\\n\\ (set_attr "mode" "none") (set_attr "length" "6")]) -;; ??? This is a hack to work around a problem with expand_builtin_setjmp. -;; It restores the frame pointer, and then does a call to restore the global -;; pointer (gp) register. The call insn implicitly (via the assembler) reloads -;; gp from the stack. However, call insns do not depend on $fp, so it is -;; possible for the instruction scheduler to move the fp restore after the -;; call, which then causes gp to be corrupted. We fix this by emitting a -;; scheduler barrier. A better fix is to put code here that restores the -;; $gp, and then the call is unnecessary. This is only a problem when PIC -;; (TARGET_ABICALLS), and only when the gp register is caller-saved -;; (irix5/o32, but not irix6/n32/n64). - -(define_expand "nonlocal_goto_receiver" - [(const_int 0)] - "" +;; For o32/n32/n64, we save the gp in the jmp_buf as well. While it is +;; possible to either pull it off the stack (in the o32 case) or recalculate +;; it given t9 and our target label, it takes 3 or 4 insns to do so, and +;; this is easy. + +(define_expand "builtin_setjmp_setup" + [(unspec [(match_operand 0 "register_operand" "r")] 20)] + "TARGET_ABICALLS" " { - emit_insn (gen_blockage ()); + if (TARGET_LONG64) + emit_insn (gen_builtin_setjmp_setup_64 (operands[0])); + else + emit_insn (gen_builtin_setjmp_setup_32 (operands[0])); + DONE; }") -;; For n32/n64, we need to restore gp after a builtin setjmp. We do this -;; by making use of the fact that we've just called __dummy. +(define_expand "builtin_setjmp_setup_32" + [(set (mem:SI (plus:SI (match_operand:SI 0 "register_operand" "r") + (const_int 12))) + (reg:SI 28))] + "TARGET_ABICALLS && ! TARGET_LONG64" + "") -(define_expand "builtin_setjmp_receiver" - [(const_int 0)] - "TARGET_ABICALLS && mips_abi != ABI_32" +(define_expand "builtin_setjmp_setup_64" + [(set (mem:DI (plus:DI (match_operand:DI 0 "register_operand" "r") + (const_int 24))) + (reg:DI 28))] + "TARGET_ABICALLS && TARGET_LONG64" + "") + +;; For o32/n32/n64, we need to arrange for longjmp to put the +;; target address in t9 so that we can use it for loading $gp. + +(define_expand "builtin_longjmp" + [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)] + "TARGET_ABICALLS" " { - emit_insn (gen_loadgp (gen_rtx (SYMBOL_REF, Pmode, \"__dummy\"))); - emit_insn (gen_blockage ()); + /* The elements of the buffer are, in order: */ + int W = (TARGET_LONG64 ? 8 : 4); + rtx fp = gen_rtx_MEM (Pmode, operands[0]); + rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 1*W)); + rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2*W)); + rtx gpv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 3*W)); + rtx pv = gen_rtx_REG (Pmode, 25); + rtx gp = gen_rtx_REG (Pmode, 28); + + /* This bit is the same as expand_builtin_longjmp. */ + emit_move_insn (hard_frame_pointer_rtx, fp); + emit_move_insn (pv, lab); + emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX); + emit_move_insn (gp, gpv); + 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, gp)); + emit_indirect_jump (pv); + DONE; }") ;; diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md index 0cd564baa34..cf3c6c524f9 100644 --- a/gcc/config/sparc/sparc.md +++ b/gcc/config/sparc/sparc.md @@ -5640,7 +5640,7 @@ (define_insn "update_return" [(unspec:SI [(match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "register_operand" "r")] 0)] + (match_operand:SI 1 "register_operand" "r")] 1)] "! TARGET_ARCH64" "cmp %1,0\;be,a .+8\;add %0,4,%0" [(set_attr "type" "multi")]) @@ -5676,32 +5676,40 @@ ;; ??? Doesn't work with -mflat. (define_expand "nonlocal_goto" - [(match_operand:SI 0 "general_operand" "") + [(match_operand:SI 0 "" "") (match_operand:SI 1 "general_operand" "") (match_operand:SI 2 "general_operand" "") - (match_operand:SI 3 "" "")] + (match_operand:SI 3 "general_operand" "")] "" " { + rtx chain = operands[0]; + rtx fp = operands[1]; + rtx stack = operands[2]; + rtx lab = operands[3]; + /* Trap instruction to flush all the register windows. */ emit_insn (gen_flush_register_windows ()); - /* Load the fp value for the containing fn into %fp. - This is needed because operands[2] refers to %fp. - Virtual register instantiation fails if the virtual %fp isn't set from a - register. Thus we must copy operands[0] into a register if it isn't - already one. */ - if (GET_CODE (operands[0]) != REG) - operands[0] = force_reg (Pmode, operands[0]); - emit_move_insn (virtual_stack_vars_rtx, operands[0]); + + /* Load the fp value for the containing fn into %fp. This is needed + because STACK refers to %fp. Note that virtual register instantiation + fails if the virtual %fp isn't set from a register. */ + if (GET_CODE (fp) != REG) + fp = force_reg (Pmode, fp); + emit_move_insn (virtual_stack_vars_rtx, fp); + /* Find the containing function's current nonlocal goto handler, which will do any cleanups and then jump to the label. */ - emit_move_insn (gen_rtx (REG, Pmode, 8), operands[1]); + emit_move_insn (gen_rtx (REG, Pmode, 8), lab); + /* Restore %fp from stack pointer value for containing function. The restore insn that follows will move this to %sp, and reload the appropriate value into %fp. */ - emit_move_insn (frame_pointer_rtx, operands[2]); + emit_move_insn (frame_pointer_rtx, stack); + /* Put in the static chain register the nonlocal label address. */ - emit_move_insn (static_chain_rtx, operands[3]); + emit_move_insn (static_chain_rtx, chain); + /* USE of frame_pointer_rtx added for consistency; not clear if really needed. */ emit_insn (gen_rtx (USE, VOIDmode, frame_pointer_rtx)); @@ -5729,11 +5737,10 @@ [(set_attr "type" "misc") (set_attr "length" "2")]) -;; Pattern for use after a setjmp to store FP and the return register -;; into the stack area. +;; Implement setjmp. Step one, set up the buffer. -(define_expand "setjmp" - [(const_int 0)] +(define_expand "builtin_setjmp_setup" + [(unspec [(match_operand 0 "" "")] 3)] "" " { @@ -5741,7 +5748,6 @@ emit_insn (gen_setjmp_64 ()); else emit_insn (gen_setjmp_32 ()); - DONE; }") diff --git a/gcc/except.c b/gcc/except.c index fce1b723806..12abb103d65 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -945,15 +945,18 @@ 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. */ emit_move_insn (dhc, XEXP (arg, 0)); 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 (); diff --git a/gcc/expr.h b/gcc/expr.h index e818d5ab398..080992f3dd9 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -752,7 +752,7 @@ 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)); +extern rtx expand_builtin_setjmp PROTO((rtx, rtx, rtx, rtx)); #ifdef TREE_CODE /* Generate code for computing expression EXP. -- 2.30.2