diff options
Diffstat (limited to 'contrib/gcc/expr.c')
-rw-r--r-- | contrib/gcc/expr.c | 140 |
1 files changed, 52 insertions, 88 deletions
diff --git a/contrib/gcc/expr.c b/contrib/gcc/expr.c index b8bcc86..e3fe1f8 100644 --- a/contrib/gcc/expr.c +++ b/contrib/gcc/expr.c @@ -192,7 +192,6 @@ static rtx expand_builtin PROTO((tree, rtx, rtx, static int apply_args_size PROTO((void)); static int apply_result_size PROTO((void)); static rtx result_vector PROTO((int, rtx)); -static rtx expand_builtin_setjmp PROTO((tree, rtx)); static rtx expand_builtin_apply_args PROTO((void)); static rtx expand_builtin_apply PROTO((rtx, rtx, rtx)); static void expand_builtin_return PROTO((rtx)); @@ -8545,29 +8544,44 @@ expand_builtin_return_addr (fndecl_code, count, tem) return tem; } -/* Construct the leading half of a __builtin_setjmp call. Control will - return to RECEIVER_LABEL. This is used directly by sjlj exception - handling code. */ +/* __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. -void -expand_builtin_setjmp_setup (buf_addr, receiver_label) + 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, first_label, next_label) rtx buf_addr; - rtx receiver_label; + rtx target; + rtx first_label, next_label; { + rtx lab1 = gen_label_rtx (); enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); + enum machine_mode value_mode; rtx stack_save; + 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 (); - /* We store the frame pointer and the address of receiver_label in - the buffer and use the rest of it for the stack save area, which - is machine-dependent. */ + /* 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. */ #ifndef BUILTIN_SETJMP_FRAME_VALUE #define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx @@ -8579,7 +8593,7 @@ expand_builtin_setjmp_setup (buf_addr, receiver_label) (gen_rtx_MEM (Pmode, plus_constant (buf_addr, GET_MODE_SIZE (Pmode)))), - force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label))); + force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, lab1))); stack_save = gen_rtx_MEM (sa_mode, plus_constant (buf_addr, @@ -8592,22 +8606,20 @@ expand_builtin_setjmp_setup (buf_addr, receiver_label) emit_insn (gen_builtin_setjmp_setup (buf_addr)); #endif - /* Tell optimize_save_area_alloca that extra work is going to - need to go on during alloca. */ - current_function_calls_setjmp = 1; + /* Set TARGET to zero and branch to the first-time-through label. */ + emit_move_insn (target, const0_rtx); + emit_jump_insn (gen_jump (first_label)); + emit_barrier (); + emit_label (lab1); + + /* Tell flow about the strange goings on. Putting `lab1' on + `nonlocal_goto_handler_labels' to indicates that function + calls may traverse the arc back to this label. */ - /* Set this so all the registers get saved in our frame; we need to be - able to copy the saved values for any registers from frames we unwind. */ current_function_has_nonlocal_label = 1; -} + nonlocal_goto_handler_labels = + gen_rtx_EXPR_LIST (VOIDmode, lab1, nonlocal_goto_handler_labels); -/* Construct the trailing part of a __builtin_setjmp call. - This is used directly by sjlj exception handling code. */ - -void -expand_builtin_setjmp_receiver (receiver_label) - rtx receiver_label ATTRIBUTE_UNUSED; -{ /* 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)); @@ -8654,7 +8666,7 @@ expand_builtin_setjmp_receiver (receiver_label) #ifdef HAVE_builtin_setjmp_receiver if (HAVE_builtin_setjmp_receiver) - emit_insn (gen_builtin_setjmp_receiver (receiver_label)); + emit_insn (gen_builtin_setjmp_receiver (lab1)); else #endif #ifdef HAVE_nonlocal_goto_receiver @@ -8666,67 +8678,11 @@ expand_builtin_setjmp_receiver (receiver_label) ; /* Nothing */ } - /* @@@ This is a kludge. Not all machine descriptions define a blockage - insn, but we must not allow the code we just generated to be reordered - by scheduling. Specifically, the update of the frame pointer must - happen immediately, not later. So emit an ASM_INPUT to act as blockage - insn. */ - emit_insn (gen_rtx_ASM_INPUT (VOIDmode, "")); -} - - -/* __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. */ - -static rtx -expand_builtin_setjmp (arglist, target) - tree arglist; - rtx target; -{ - rtx buf_addr, next_lab, cont_lab; - - if (arglist == 0 - || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE) - return NULL_RTX; - - if (target == 0 || GET_CODE (target) != REG - || REGNO (target) < FIRST_PSEUDO_REGISTER) - target = gen_reg_rtx (TYPE_MODE (integer_type_node)); - - buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0); - - next_lab = gen_label_rtx (); - cont_lab = gen_label_rtx (); - - expand_builtin_setjmp_setup (buf_addr, next_lab); - - /* Set TARGET to zero and branch to the continue label. */ - emit_move_insn (target, const0_rtx); - emit_jump_insn (gen_jump (cont_lab)); - emit_barrier (); - emit_label (next_lab); - - expand_builtin_setjmp_receiver (next_lab); - - /* Set TARGET to one. */ + /* Set TARGET, and branch to the next-time-through label. */ emit_move_insn (target, const1_rtx); - emit_label (cont_lab); - - /* Tell flow about the strange goings on. Putting `next_lab' on - `nonlocal_goto_handler_labels' to indicates that function - calls may traverse the arc back to this label. */ + emit_jump_insn (gen_jump (next_label)); + emit_barrier (); - current_function_has_nonlocal_label = 1; - nonlocal_goto_handler_labels - = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels); - return target; } @@ -9747,10 +9703,18 @@ expand_builtin (exp, target, subtarget, mode, ignore) #endif case BUILT_IN_SETJMP: - target = expand_builtin_setjmp (arglist, target); - if (target) - return target; - break; + 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; + } /* __builtin_longjmp is passed a pointer to an array of five words. It's similar to the C library longjmp function but works with |