expr.c (72562) | expr.c (74473) |
---|---|
1/* Convert tree expression to rtl instructions, for GNU compiler. 2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 3 2000, 2001 Free Software Foundation, Inc. 4 5This file is part of GNU CC. 6 7GNU CC is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by --- 178 unchanged lines hidden (view full) --- 187static tree string_constant PROTO((tree, tree *)); 188static tree c_strlen PROTO((tree)); 189static rtx get_memory_rtx PROTO((tree)); 190static rtx expand_builtin PROTO((tree, rtx, rtx, 191 enum machine_mode, int)); 192static int apply_args_size PROTO((void)); 193static int apply_result_size PROTO((void)); 194static rtx result_vector PROTO((int, rtx)); | 1/* Convert tree expression to rtl instructions, for GNU compiler. 2 Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 3 2000, 2001 Free Software Foundation, Inc. 4 5This file is part of GNU CC. 6 7GNU CC is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by --- 178 unchanged lines hidden (view full) --- 187static tree string_constant PROTO((tree, tree *)); 188static tree c_strlen PROTO((tree)); 189static rtx get_memory_rtx PROTO((tree)); 190static rtx expand_builtin PROTO((tree, rtx, rtx, 191 enum machine_mode, int)); 192static int apply_args_size PROTO((void)); 193static int apply_result_size PROTO((void)); 194static rtx result_vector PROTO((int, rtx)); |
195static rtx expand_builtin_setjmp PROTO((tree, rtx)); | |
196static rtx expand_builtin_apply_args PROTO((void)); 197static rtx expand_builtin_apply PROTO((rtx, rtx, rtx)); 198static void expand_builtin_return PROTO((rtx)); 199static rtx expand_increment PROTO((tree, int, int)); 200static void preexpand_calls PROTO((tree)); 201static void do_jump_by_parts_greater PROTO((tree, int, rtx, rtx)); 202static void do_jump_by_parts_equality PROTO((tree, rtx, rtx)); 203static void do_jump_for_compare PROTO((rtx, rtx, rtx)); --- 8336 unchanged lines hidden (view full) --- 8540#else 8541 tem = memory_address (Pmode, 8542 plus_constant (tem, GET_MODE_SIZE (Pmode))); 8543 tem = gen_rtx_MEM (Pmode, tem); 8544#endif 8545 return tem; 8546} 8547 | 195static rtx expand_builtin_apply_args PROTO((void)); 196static rtx expand_builtin_apply PROTO((rtx, rtx, rtx)); 197static void expand_builtin_return PROTO((rtx)); 198static rtx expand_increment PROTO((tree, int, int)); 199static void preexpand_calls PROTO((tree)); 200static void do_jump_by_parts_greater PROTO((tree, int, rtx, rtx)); 201static void do_jump_by_parts_equality PROTO((tree, rtx, rtx)); 202static void do_jump_for_compare PROTO((rtx, rtx, rtx)); --- 8336 unchanged lines hidden (view full) --- 8539#else 8540 tem = memory_address (Pmode, 8541 plus_constant (tem, GET_MODE_SIZE (Pmode))); 8542 tem = gen_rtx_MEM (Pmode, tem); 8543#endif 8544 return tem; 8545} 8546 |
8548/* Construct the leading half of a __builtin_setjmp call. Control will 8549 return to RECEIVER_LABEL. This is used directly by sjlj exception 8550 handling code. */ | 8547/* __builtin_setjmp is passed a pointer to an array of five words (not 8548 all will be used on all machines). It operates similarly to the C 8549 library function of the same name, but is more efficient. Much of 8550 the code below (and for longjmp) is copied from the handling of 8551 non-local gotos. |
8551 | 8552 |
8552void 8553expand_builtin_setjmp_setup (buf_addr, receiver_label) | 8553 NOTE: This is intended for use by GNAT and the exception handling 8554 scheme in the compiler and will only work in the method used by 8555 them. */ 8556 8557rtx 8558expand_builtin_setjmp (buf_addr, target, first_label, next_label) |
8554 rtx buf_addr; | 8559 rtx buf_addr; |
8555 rtx receiver_label; | 8560 rtx target; 8561 rtx first_label, next_label; |
8556{ | 8562{ |
8563 rtx lab1 = gen_label_rtx (); |
|
8557 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); | 8564 enum machine_mode sa_mode = STACK_SAVEAREA_MODE (SAVE_NONLOCAL); |
8565 enum machine_mode value_mode; |
|
8558 rtx stack_save; 8559 | 8566 rtx stack_save; 8567 |
8568 value_mode = TYPE_MODE (integer_type_node); 8569 |
|
8560#ifdef POINTERS_EXTEND_UNSIGNED 8561 buf_addr = convert_memory_address (Pmode, buf_addr); 8562#endif 8563 8564 buf_addr = force_reg (Pmode, buf_addr); 8565 | 8570#ifdef POINTERS_EXTEND_UNSIGNED 8571 buf_addr = convert_memory_address (Pmode, buf_addr); 8572#endif 8573 8574 buf_addr = force_reg (Pmode, buf_addr); 8575 |
8576 if (target == 0 || GET_CODE (target) != REG 8577 || REGNO (target) < FIRST_PSEUDO_REGISTER) 8578 target = gen_reg_rtx (value_mode); 8579 |
|
8566 emit_queue (); 8567 | 8580 emit_queue (); 8581 |
8568 /* We store the frame pointer and the address of receiver_label in 8569 the buffer and use the rest of it for the stack save area, which 8570 is machine-dependent. */ | 8582 /* We store the frame pointer and the address of lab1 in the buffer 8583 and use the rest of it for the stack save area, which is 8584 machine-dependent. */ |
8571 8572#ifndef BUILTIN_SETJMP_FRAME_VALUE 8573#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx 8574#endif 8575 8576 emit_move_insn (gen_rtx_MEM (Pmode, buf_addr), 8577 BUILTIN_SETJMP_FRAME_VALUE); 8578 emit_move_insn (validize_mem 8579 (gen_rtx_MEM (Pmode, 8580 plus_constant (buf_addr, 8581 GET_MODE_SIZE (Pmode)))), | 8585 8586#ifndef BUILTIN_SETJMP_FRAME_VALUE 8587#define BUILTIN_SETJMP_FRAME_VALUE virtual_stack_vars_rtx 8588#endif 8589 8590 emit_move_insn (gen_rtx_MEM (Pmode, buf_addr), 8591 BUILTIN_SETJMP_FRAME_VALUE); 8592 emit_move_insn (validize_mem 8593 (gen_rtx_MEM (Pmode, 8594 plus_constant (buf_addr, 8595 GET_MODE_SIZE (Pmode)))), |
8582 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, receiver_label))); | 8596 force_reg (Pmode, gen_rtx_LABEL_REF (Pmode, lab1))); |
8583 8584 stack_save = gen_rtx_MEM (sa_mode, 8585 plus_constant (buf_addr, 8586 2 * GET_MODE_SIZE (Pmode))); 8587 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX); 8588 8589 /* If there is further processing to do, do it. */ 8590#ifdef HAVE_builtin_setjmp_setup 8591 if (HAVE_builtin_setjmp_setup) 8592 emit_insn (gen_builtin_setjmp_setup (buf_addr)); 8593#endif 8594 | 8597 8598 stack_save = gen_rtx_MEM (sa_mode, 8599 plus_constant (buf_addr, 8600 2 * GET_MODE_SIZE (Pmode))); 8601 emit_stack_save (SAVE_NONLOCAL, &stack_save, NULL_RTX); 8602 8603 /* If there is further processing to do, do it. */ 8604#ifdef HAVE_builtin_setjmp_setup 8605 if (HAVE_builtin_setjmp_setup) 8606 emit_insn (gen_builtin_setjmp_setup (buf_addr)); 8607#endif 8608 |
8595 /* Tell optimize_save_area_alloca that extra work is going to 8596 need to go on during alloca. */ 8597 current_function_calls_setjmp = 1; | 8609 /* Set TARGET to zero and branch to the first-time-through label. */ 8610 emit_move_insn (target, const0_rtx); 8611 emit_jump_insn (gen_jump (first_label)); 8612 emit_barrier (); 8613 emit_label (lab1); |
8598 | 8614 |
8599 /* Set this so all the registers get saved in our frame; we need to be 8600 able to copy the saved values for any registers from frames we unwind. */ | 8615 /* Tell flow about the strange goings on. Putting `lab1' on 8616 `nonlocal_goto_handler_labels' to indicates that function 8617 calls may traverse the arc back to this label. */ 8618 |
8601 current_function_has_nonlocal_label = 1; | 8619 current_function_has_nonlocal_label = 1; |
8602} | 8620 nonlocal_goto_handler_labels = 8621 gen_rtx_EXPR_LIST (VOIDmode, lab1, nonlocal_goto_handler_labels); |
8603 | 8622 |
8604/* Construct the trailing part of a __builtin_setjmp call. 8605 This is used directly by sjlj exception handling code. */ 8606 8607void 8608expand_builtin_setjmp_receiver (receiver_label) 8609 rtx receiver_label ATTRIBUTE_UNUSED; 8610{ | |
8611 /* Clobber the FP when we get here, so we have to make sure it's 8612 marked as used by this function. */ 8613 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); 8614 8615 /* Mark the static chain as clobbered here so life information 8616 doesn't get messed up for it. */ 8617 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx)); 8618 --- 30 unchanged lines hidden (view full) --- 8649 emit_move_insn (virtual_incoming_args_rtx, 8650 copy_to_reg (arg_pointer_save_area)); 8651 } 8652 } 8653#endif 8654 8655#ifdef HAVE_builtin_setjmp_receiver 8656 if (HAVE_builtin_setjmp_receiver) | 8623 /* Clobber the FP when we get here, so we have to make sure it's 8624 marked as used by this function. */ 8625 emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx)); 8626 8627 /* Mark the static chain as clobbered here so life information 8628 doesn't get messed up for it. */ 8629 emit_insn (gen_rtx_CLOBBER (VOIDmode, static_chain_rtx)); 8630 --- 30 unchanged lines hidden (view full) --- 8661 emit_move_insn (virtual_incoming_args_rtx, 8662 copy_to_reg (arg_pointer_save_area)); 8663 } 8664 } 8665#endif 8666 8667#ifdef HAVE_builtin_setjmp_receiver 8668 if (HAVE_builtin_setjmp_receiver) |
8657 emit_insn (gen_builtin_setjmp_receiver (receiver_label)); | 8669 emit_insn (gen_builtin_setjmp_receiver (lab1)); |
8658 else 8659#endif 8660#ifdef HAVE_nonlocal_goto_receiver 8661 if (HAVE_nonlocal_goto_receiver) 8662 emit_insn (gen_nonlocal_goto_receiver ()); 8663 else 8664#endif 8665 { 8666 ; /* Nothing */ 8667 } 8668 | 8670 else 8671#endif 8672#ifdef HAVE_nonlocal_goto_receiver 8673 if (HAVE_nonlocal_goto_receiver) 8674 emit_insn (gen_nonlocal_goto_receiver ()); 8675 else 8676#endif 8677 { 8678 ; /* Nothing */ 8679 } 8680 |
8669 /* @@@ This is a kludge. Not all machine descriptions define a blockage 8670 insn, but we must not allow the code we just generated to be reordered 8671 by scheduling. Specifically, the update of the frame pointer must 8672 happen immediately, not later. So emit an ASM_INPUT to act as blockage 8673 insn. */ 8674 emit_insn (gen_rtx_ASM_INPUT (VOIDmode, "")); 8675} 8676 8677 8678/* __builtin_setjmp is passed a pointer to an array of five words (not 8679 all will be used on all machines). It operates similarly to the C 8680 library function of the same name, but is more efficient. Much of 8681 the code below (and for longjmp) is copied from the handling of 8682 non-local gotos. 8683 8684 NOTE: This is intended for use by GNAT and the exception handling 8685 scheme in the compiler and will only work in the method used by 8686 them. */ 8687 8688static rtx 8689expand_builtin_setjmp (arglist, target) 8690 tree arglist; 8691 rtx target; 8692{ 8693 rtx buf_addr, next_lab, cont_lab; 8694 8695 if (arglist == 0 8696 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE) 8697 return NULL_RTX; 8698 8699 if (target == 0 || GET_CODE (target) != REG 8700 || REGNO (target) < FIRST_PSEUDO_REGISTER) 8701 target = gen_reg_rtx (TYPE_MODE (integer_type_node)); 8702 8703 buf_addr = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0); 8704 8705 next_lab = gen_label_rtx (); 8706 cont_lab = gen_label_rtx (); 8707 8708 expand_builtin_setjmp_setup (buf_addr, next_lab); 8709 8710 /* Set TARGET to zero and branch to the continue label. */ 8711 emit_move_insn (target, const0_rtx); 8712 emit_jump_insn (gen_jump (cont_lab)); | 8681 /* Set TARGET, and branch to the next-time-through label. */ 8682 emit_move_insn (target, const1_rtx); 8683 emit_jump_insn (gen_jump (next_label)); |
8713 emit_barrier (); | 8684 emit_barrier (); |
8714 emit_label (next_lab); | |
8715 | 8685 |
8716 expand_builtin_setjmp_receiver (next_lab); 8717 8718 /* Set TARGET to one. */ 8719 emit_move_insn (target, const1_rtx); 8720 emit_label (cont_lab); 8721 8722 /* Tell flow about the strange goings on. Putting `next_lab' on 8723 `nonlocal_goto_handler_labels' to indicates that function 8724 calls may traverse the arc back to this label. */ 8725 8726 current_function_has_nonlocal_label = 1; 8727 nonlocal_goto_handler_labels 8728 = gen_rtx_EXPR_LIST (VOIDmode, next_lab, nonlocal_goto_handler_labels); 8729 | |
8730 return target; 8731} 8732 8733void 8734expand_builtin_longjmp (buf_addr, value) 8735 rtx buf_addr, value; 8736{ 8737 rtx fp, lab, stack; --- 1004 unchanged lines hidden (view full) --- 9742 } 9743#else 9744 case BUILT_IN_STRCMP: 9745 case BUILT_IN_MEMCMP: 9746 break; 9747#endif 9748 9749 case BUILT_IN_SETJMP: | 8686 return target; 8687} 8688 8689void 8690expand_builtin_longjmp (buf_addr, value) 8691 rtx buf_addr, value; 8692{ 8693 rtx fp, lab, stack; --- 1004 unchanged lines hidden (view full) --- 9698 } 9699#else 9700 case BUILT_IN_STRCMP: 9701 case BUILT_IN_MEMCMP: 9702 break; 9703#endif 9704 9705 case BUILT_IN_SETJMP: |
9750 target = expand_builtin_setjmp (arglist, target); 9751 if (target) 9752 return target; 9753 break; | 9706 if (arglist == 0 9707 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE) 9708 break; 9709 else 9710 { 9711 rtx buf_addr = expand_expr (TREE_VALUE (arglist), subtarget, 9712 VOIDmode, 0); 9713 rtx lab = gen_label_rtx (); 9714 rtx ret = expand_builtin_setjmp (buf_addr, target, lab, lab); 9715 emit_label (lab); 9716 return ret; 9717 } |
9754 9755 /* __builtin_longjmp is passed a pointer to an array of five words. 9756 It's similar to the C library longjmp function but works with 9757 __builtin_setjmp above. */ 9758 case BUILT_IN_LONGJMP: 9759 if (arglist == 0 || TREE_CHAIN (arglist) == 0 9760 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE) 9761 break; --- 2082 unchanged lines hidden --- | 9718 9719 /* __builtin_longjmp is passed a pointer to an array of five words. 9720 It's similar to the C library longjmp function but works with 9721 __builtin_setjmp above. */ 9722 case BUILT_IN_LONGJMP: 9723 if (arglist == 0 || TREE_CHAIN (arglist) == 0 9724 || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != POINTER_TYPE) 9725 break; --- 2082 unchanged lines hidden --- |